Introduction
Real estate agents spend hours each week transforming raw property photos into polished listings. A photographer delivers 50 images; an agent manually uploads them to a background removal tool, waits for processing, then hands off to a virtual tour platform, then writes descriptions. Each handoff is a friction point where things get lost, duplicated, or delayed.
This workflow doesn't need to be manual. By connecting three focused AI tools through an orchestration platform, you can move from photo upload to finished virtual tour with zero human intervention between steps. The entire process runs automatically, triggered by a single action: dropping photos into a folder.
We'll build this using AI-Boost for background removal and image enhancement, Hour One for AI-generated property descriptions, and PixelMotion AI for interactive virtual tours. The orchestration happens in Zapier, n8n, or Make, depending on your comfort level with configuration.
The Automated Workflow
Choosing Your Orchestration Platform
Start by deciding which orchestration tool fits your needs. Zapier works well if you want minimal configuration and don't mind paying per task. n8n is better if you want to run everything on your own infrastructure and avoid per-execution fees. Make (formerly Integromat) sits in the middle, offering reasonable pricing with more control than Zapier.
For this workflow, I'll use n8n because it handles parallel processing efficiently (you'll often need to enhance multiple images at once) and charges a flat monthly fee rather than per execution.
Step 1:
Trigger on Photo Upload
The workflow starts when real estate photos land in a cloud storage folder. We'll use Google Drive as the trigger source, though Dropbox, AWS S3, or Azure Blob Storage work equally well.
Set up an n8n workflow with a Google Drive trigger node:
Trigger: Google Drive > Watch Folder
Configuration:
- Folder ID: [Your Google Drive folder ID for property photos]
- Watch for: new files
- File extensions: .jpg, .jpeg, .png
- Trigger interval: 60 seconds
This node fires whenever a new image appears. Each trigger passes the file metadata and download URL to the next step.
Step 2:
Background Removal and Enhancement with AI-Boost
AI-Boost's API removes backgrounds and enhances images in one call. Rather than downloading the file locally, you'll send the image URL directly to their API endpoint.
Add an HTTP Request node in n8n configured like this:
Method: POST
URL: https://api.ai-boost.com/v1/process-image
Headers:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Body (JSON):
{
"image_url": "{{ $node['Google Drive'].data.webContentLink }}",
"operations": [
{
"type": "remove_background",
"params": {
"output_format": "png",
"edge_quality": "high"
}
},
{
"type": "enhance",
"params": {
"brightness": 0.1,
"contrast": 0.15,
"saturation": 0.2
}
}
],
"webhook_url": "{{ $env.N8N_WEBHOOK_URL }}/ai-boost-callback"
}
AI-Boost processes asynchronously and calls your webhook when complete. The response includes a download URL for the enhanced image.
Create a webhook node to receive the callback:
Trigger type: Webhook
HTTP method: POST
Response: 200 OK
Store the processed image URL in a temporary variable for the next step.
Step 3:
Generate Property Description with Hour One
With the enhanced image ready, generate an AI-written property description. Hour One's API analyses the image content and produces marketing copy.
Add another HTTP Request node:
Method: POST
URL: https://api.hourone.com/v2/generate-description
Headers:
Authorization: Bearer YOUR_HOUR_ONE_API_KEY
Content-Type: application/json
Body (JSON):
{
"image_url": "{{ $node['AI-Boost Webhook'].data.enhanced_image_url }}",
"property_type": "residential",
"tone": "professional",
"length": "medium",
"include_features": [
"lighting",
"space",
"finishes",
"architectural_details"
],
"async": true,
"callback_url": "{{ $env.N8N_WEBHOOK_URL }}/hourone-callback"
}
Hour One returns a job ID immediately; the actual description arrives asynchronously. Create a second webhook to receive it:
Trigger type: Webhook
HTTP method: POST
Path: /hourone-callback
The response contains the generated description text. Store this in your workflow state.
Step 4:
Build Virtual Tour with PixelMotion AI
Now that you have the enhanced image and description, create an interactive virtual tour. PixelMotion AI generates 360-degree tours from 2D images using AI upscaling and spatial inference.
Add an HTTP Request node for PixelMotion:
Method: POST
URL: https://api.pixelmotion.ai/v1/create-tour
Headers:
Authorization: Bearer YOUR_PIXELMOTION_API_KEY
Content-Type: application/json
Body (JSON):
{
"images": [
{
"url": "{{ $node['AI-Boost Webhook'].data.enhanced_image_url }}",
"room_type": "living_room",
"position": 0
}
],
"tour_settings": {
"quality": "high",
"enable_hotspots": true,
"auto_pan": true,
"description": "{{ $node['Hour One Webhook'].data.description }}"
},
"output_format": "web_embed",
"webhook_url": "{{ $env.N8N_WEBHOOK_URL }}/pixelmotion-callback"
}
PixelMotion processes the image set and generates an embeddable HTML widget. It also returns URLs for standalone viewing.
Create a third webhook to capture the result:
Trigger type: Webhook
HTTP method: POST
Path: /pixelmotion-callback
Step 5:
Save Results and Notify
Once all three services complete, aggregate the data and save it back to a structured location. Use a Google Sheets node to log the results:
Node type: Google Sheets
Operation: Append
Spreadsheet: [Your real estate listings sheet]
Sheet: Processed Listings
Data to append:
- Property ID: {{ $node['Google Drive'].data.name }}
- Original image URL: {{ $node['Google Drive'].data.webContentLink }}
- Enhanced image URL: {{ $node['AI-Boost Webhook'].data.enhanced_image_url }}
- Description: {{ $node['Hour One Webhook'].data.description }}
- Tour embed code: {{ $node['PixelMotion Webhook'].data.embed_html }}
- Tour URL: {{ $node['PixelMotion Webhook'].data.public_url }}
- Processed at: {{ new Date().toISOString() }}
Finish with a notification to let your team know the listing is ready:
Node type: Slack
Channel: #property-listings
Message:
New listing processed: {{ $node['Google Drive'].data.name }}
Enhanced image: {{ $node['AI-Boost Webhook'].data.enhanced_image_url }}
View tour: {{ $node['PixelMotion Webhook'].data.public_url }}
Alternatively, send an email using n8n's Gmail node or a third-party service like SendGrid.
Handling Multiple Images per Property
Most properties have multiple rooms. Modify the workflow to handle batches. Instead of processing one image, group them by property ID (you could use folder structure or filename prefixes like "PROP001-livingroom.jpg").
Use an n8n "Function" node to batch images:
const images = $node['Google Drive'].data.map(file => ({
name: file.name,
url: file.webContentLink,
propertyId: file.name.split('-')[0],
roomType: file.name.split('-')[1].replace('.jpg', '')
}));
const grouped = {};
images.forEach(img => {
if (!grouped[img.propertyId]) {
grouped[img.propertyId] = [];
}
grouped[img.propertyId].push(img);
});
return Object.entries(grouped).map(([propId, imgs]) => ({
property_id: propId,
images: imgs
}));
Then loop through each property batch, processing all images in parallel before passing them to PixelMotion.
The Manual Alternative
If full automation feels premature, you can use these three tools with manual orchestration. Process images through AI-Boost directly on their web platform, copy the enhanced images into Hour One's interface, then upload results to PixelMotion. This takes longer but requires no workflow configuration and gives you fine-grained control over each step. You might choose this approach while testing the quality of AI-generated descriptions, adjusting parameters, or handling edge cases (unusual properties, mixed indoor/outdoor spaces).
Pro Tips
1. Handle Rate Limiting Gracefully
AI-Boost, Hour One, and PixelMotion all have rate limits. If you process 50 properties in a batch, you'll hit them. In n8n, add a "Wait" node between iterations:
Node type: Wait
Trigger: Time interval
Interval: 2 seconds
Alternatively, check the 429 response code and implement exponential backoff:
Node type: Function
Code:
const maxRetries = 3;
let delay = 1000;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await makeApiCall();
if (response.status === 429) {
await new Promise(resolve => setTimeout(resolve, delay));
delay *= 2;
continue;
}
return response;
} catch (error) {
console.error(`Attempt ${attempt + 1} failed`, error);
}
}
2. Store API Responses for Debugging
When things fail, you need a record. After each API call, log the full response to a debugging sheet or cloud storage:
Node type: Google Sheets
Operation: Append
Data:
- Timestamp: {{ new Date().toISOString() }}
- API endpoint: {{ $node['HTTP Request'].data.url }}
- Status: {{ $node['HTTP Request'].data.statusCode }}
- Response body: {{ JSON.stringify($node['HTTP Request'].data) }}
- Error: {{ $node['HTTP Request'].data.error }}
3. Validate Image Quality Before Processing
Not all photos are suitable for background removal or tour generation. Add a pre-flight check using a simple image analysis API or n8n's built-in conditions:
Node type: IF
Condition:
- Image dimensions >= 1920 x 1440
- File size <= 50 MB
- Image format in [jpg, png]
If true: Continue to AI-Boost
If false: Log error and skip
4. Re-use Enhanced Images Across Properties
If you're processing multiple rooms in the same property, don't enhance the same image twice. Cache results in memory or a temp database:
Node type: Function
Code:
const cache = $node['Google Drive'].data.cache || {};
const imageHash = crypto.createHash('md5')
.update(file.url)
.digest('hex');
if (cache[imageHash]) {
return cache[imageHash];
}
const enhanced = await aiBoostApi(file.url);
cache[imageHash] = enhanced;
return enhanced;
5. Monitor Costs Actively
Each API call costs money. AI-Boost charges per image, Hour One per description, PixelMotion per tour. Add a cost calculation node:
Node type: Function
Code:
const costs = {
ai_boost_per_image: 0.08,
hour_one_per_description: 0.15,
pixelmotion_per_tour: 0.25
};
const totalCost = (imageCount * costs.ai_boost_per_image) +
(descriptionCount * costs.hour_one_per_description) +
(tourCount * costs.pixelmotion_per_tour);
return { monthly_estimate: totalCost * 30 };
Track monthly spend in a sheet so you can adjust batch sizes or processing frequency if needed.
Cost Breakdown
| Tool | Plan Needed | Monthly Cost | Notes |
|---|---|---|---|
| AI-Boost | Pay-as-you-go | £0.08 per image | ~240 images @ £20 |
| Hour One | API access | £0.15 per description | ~200 descriptions @ £30 |
| PixelMotion AI | Pro | £0.25 per tour | ~150 tours @ £37.50 |
| n8n (Self-hosted) | Community (free) or Cloud Pro | £0–£150 | Free if self-hosted; Pro for reliability |
| Google Drive | Free tier or Workspace | £0–£12 | 15 GB free; Workspace £12/user |
| Google Sheets | Included with Drive | Included | Unlimited cells and sheets |
| Slack or email | Free or included | £0–£8 | Notifications only |
| Total estimate | All tools | £87–£240 | For ~200–300 properties monthly |
The figures assume moderate usage. High-volume agencies (500+ listings monthly) should negotiate volume discounts with AI-Boost and PixelMotion, potentially cutting per-unit costs by 20–30%.