This workflow corresponds to n8n.io template #17510 — we link there as the canonical source.
This workflow follows the Agent → Emailsend recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "TuCCJd7wyzGdDiJk",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Create real estate listing packages from room photos with Anthropic Claude",
"tags": [],
"nodes": [
{
"id": "1f9ce148-4e08-4032-8ac4-03dd44ae0485",
"name": "Sticky Note - Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
-640
],
"parameters": {
"color": "#FFF700",
"width": 940,
"height": 1108,
"content": "## Empty-Room to Full-Listing Pipeline\n\nTurn a single empty-room photo into a ready-to-publish real estate listing: an AI-staged render, a comp-based price recommendation, and AI-written listing copy \u2014 delivered straight to your inbox.\n\nBuilt for real estate agents, property managers, and listing platforms who want a listing-ready package minutes after a photo shoot, not days.\n\n### How it works\n1. A form captures the empty-room photo plus property basics (address, type, beds, baths, square footage).\n2. Two APIs run in parallel: a virtual-staging/3D-rendering API furnishes and styles the room and returns a walkthrough link, while a comps API pulls recent comparable sales near the address.\n3. A Code node merges both responses into pricing inputs: average comp price, price-per-sqft, and a suggested price range.\n4. Claude writes the listing title, description, key selling points, and a suggested list price.\n5. A Code node parses the AI output into structured data (with a rule-based fallback if parsing fails), then assembles the final package.\n6. The complete listing is emailed to the agent, ready to publish.\n\n### Setup\n1. Import this workflow into n8n.\n2. Add your Anthropic Claude credentials to the Anthropic model node.\n3. Add your virtual-staging/3D-rendering API credentials to Fetch AI Virtual Staging Render.\n4. Add your comps/market-data API credentials to Fetch Comparable Listings & Market Data.\n5. Add SMTP credentials to Send Full Listing Package Email and update the from/to addresses.\n6. Activate the workflow and open the form URL to submit a room photo.\n\n### Customization\n- Add staging style options (Modern, Traditional, Scandinavian) as a form field.\n- Log every generated listing to a Google Sheet or CRM.\n- Add a second AI pass to generate social captions from the listing copy.\n- Push the finished listing directly into your MLS or listing platform instead of email."
},
"typeVersion": 1
},
{
"id": "a3cbc4d4-aec9-4930-84b6-29feedcf02ee",
"name": "Sticky Note - Stage 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
2208,
-368
],
"parameters": {
"color": 4,
"width": 1300,
"height": 760,
"content": "## Stage 1: Photo In, Staging & Comps Out\n\nThe form captures the room photo and property details. Two APIs run in parallel \u2014 AI staging/3D render and comps data. A Code node merges them into pricing inputs (avg price, price/sqft, suggested range)."
},
"typeVersion": 1
},
{
"id": "c6d84e5b-475a-4e36-8fee-d4d38ee7d3a9",
"name": "Sticky Note - Stage 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
3552,
-352
],
"parameters": {
"color": 3,
"width": 1028,
"height": 760,
"content": "## Stage 2: AI Copywriting\n\nA short wait respects API rate limits. Claude then turns the staged render, comp pricing, and property details into a listing title, description, selling points, and suggested list price."
},
"typeVersion": 1
},
{
"id": "c5323703-a0b9-4448-b5b4-f382b14c8907",
"name": "Sticky Note - Stage 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
4704,
-368
],
"parameters": {
"color": 4,
"width": 892,
"height": 760,
"content": "## Stage 3: Assemble & Deliver\n\nA Code node parses the AI output (with a rule-based fallback), then another assembles the staged image, 3D link, comp pricing, and copy into one package \u2014 emailed to the agent, ready to publish."
},
"typeVersion": 1
},
{
"id": "200f265a-3e46-43ce-a10f-7941661cce9a",
"name": "Form - Upload Empty Room Photo",
"type": "n8n-nodes-base.formTrigger",
"position": [
2304,
96
],
"parameters": {
"options": {},
"formTitle": "=",
"formFields": {
"values": [
{
"fieldType": "file",
"fieldLabel": "Empty Room Photo",
"requiredField": true
},
{
"fieldLabel": "Property Address",
"requiredField": true
},
{
"fieldType": "dropdown",
"fieldLabel": "Property Type",
"fieldOptions": {
"values": [
{
"option": "Single Family Home"
},
{
"option": "Condo"
},
{
"option": "Townhouse"
},
{
"option": "Apartment"
}
]
},
"requiredField": true
},
{
"fieldType": "number",
"fieldLabel": "Bedrooms"
},
{
"fieldType": "number",
"fieldLabel": "Bathrooms"
},
{
"fieldType": "number",
"fieldLabel": "Square Feet"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b1483cae-63f2-4d19-bb71-0a4913475fb3",
"name": "Fetch AI Virtual Staging Render",
"type": "n8n-nodes-base.httpRequest",
"position": [
2624,
-48
],
"parameters": {
"url": "https://api.staging-provider.example.com/v1/render",
"method": "POST",
"options": {},
"jsonBody": "={\n \"image_base64\": \"{{ $json['Empty Room Photo'] }}\",\n \"style\": \"Modern\",\n \"output_types\": [\"staged_image\", \"3d_walkthrough\"]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "38533782-3776-475f-b2f1-8a90a8fb749b",
"name": "Fetch Comparable Listings & Market Data",
"type": "n8n-nodes-base.httpRequest",
"position": [
2624,
224
],
"parameters": {
"url": "=https://api.comps-provider.example.com/v1/comparables?address={{ encodeURIComponent($json['Property Address']) }}&beds={{ $json['Bedrooms'] }}&baths={{ $json['Bathrooms'] }}&sqft={{ $json['Square Feet'] }}",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "7d5a274f-ebb5-4c17-85a8-cc3b9bbdd31f",
"name": "Merge - Combine Staging & Comps Data",
"type": "n8n-nodes-base.merge",
"position": [
2960,
96
],
"parameters": {
"mode": "combine",
"options": {}
},
"typeVersion": 3.2
},
{
"id": "b64c9bd3-5b0f-46aa-a868-253840c03e1f",
"name": "JS - Build Property Baseline & Pricing Inputs",
"type": "n8n-nodes-base.code",
"position": [
3280,
96
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const item = $input.item.json;\nconst formData = $('Form - Upload Empty Room Photo').first().json;\n\nconst stagedImageUrl = item.stagedImageUrl || item.staged_image_url || '';\nconst walkthrough3dUrl = item.walkthrough3dUrl || item['3d_walkthrough_url'] || '';\nconst styleApplied = item.styleApplied || item.style || 'Modern';\n\nconst comparables = item.comparables || item.comps || [];\n\nconst prices = comparables\n .map(c => parseFloat(c.price))\n .filter(p => !isNaN(p) && p > 0);\n\nconst avgCompPrice = prices.length\n ? Math.round(prices.reduce((sum, p) => sum + p, 0) / prices.length)\n : null;\n\nconst pricePerSqftValues = comparables\n .map(c => {\n const p = parseFloat(c.price);\n const s = parseFloat(c.squareFeet || c.sqft);\n return (!isNaN(p) && !isNaN(s) && s > 0) ? p / s : null;\n })\n .filter(v => v !== null);\n\nconst avgPricePerSqft = pricePerSqftValues.length\n ? Math.round((pricePerSqftValues.reduce((sum, v) => sum + v, 0) / pricePerSqftValues.length) * 100) / 100\n : null;\n\nconst squareFeet = parseFloat(formData['Square Feet']) || 0;\n\nconst estimatedValueFromComps = avgPricePerSqft && squareFeet\n ? Math.round(avgPricePerSqft * squareFeet)\n : avgCompPrice;\n\nconst suggestedPriceLow = estimatedValueFromComps ? Math.round(estimatedValueFromComps * 0.97) : null;\nconst suggestedPriceHigh = estimatedValueFromComps ? Math.round(estimatedValueFromComps * 1.03) : null;\n\nreturn {\n json: {\n address: formData['Property Address'],\n propertyType: formData['Property Type'],\n bedrooms: parseInt(formData['Bedrooms'], 10) || 0,\n bathrooms: parseFloat(formData['Bathrooms']) || 0,\n squareFeet,\n stagedImageUrl, walkthrough3dUrl, styleApplied,\n comparableCount: comparables.length,\n avgCompPrice, avgPricePerSqft,\n suggestedPriceLow, suggestedPriceHigh, estimatedValueFromComps\n }\n};"
},
"typeVersion": 2
},
{
"id": "78800387-6498-4131-b7a1-96176f87cc0e",
"name": "Wait For Staging & Comps Buffer",
"type": "n8n-nodes-base.wait",
"position": [
3600,
96
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "e2368acd-19cf-4ca9-933d-40127e0c6ab9",
"name": "AI - Generate Listing Copy & Price Recommendation",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
3984,
96
],
"parameters": {
"text": "=You are a real estate copywriter creating a listing from a newly staged room render and comparable-sales pricing data.\n\nProperty:\nAddress: {{ $json.address }}\nType: {{ $json.propertyType }}\nBedrooms: {{ $json.bedrooms }} | Bathrooms: {{ $json.bathrooms }} | Square Feet: {{ $json.squareFeet }}\nStaging Style Applied: {{ $json.styleApplied }}\n\nComp-Based Pricing ({{ $json.comparableCount }} comparables):\nAverage Comp Price: ${{ $json.avgCompPrice }}\nAverage Price per Sqft: ${{ $json.avgPricePerSqft }}\nEstimated Value: ${{ $json.estimatedValueFromComps }}\nSuggested Price Range: ${{ $json.suggestedPriceLow }} - ${{ $json.suggestedPriceHigh }}\n\nWrite a compelling MLS-style listing based on this data.\n\nReturn a JSON object with EXACTLY these fields:\n{\n \"listingTitle\": \"short punchy headline, under 12 words\",\n \"listingDescription\": \"3-4 sentence listing description highlighting the staged look and property features\",\n \"keySellingPoints\": [\"point 1\", \"point 2\", \"point 3\"],\n \"suggestedListPrice\": number, choose a single price within the suggested range\n}\n\nReturn ONLY the JSON. No markdown, no explanation.",
"options": {},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "3286b901-ae22-4ef8-88ac-8254686e0188",
"name": "Anthropic - Copywriting Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
3856,
240
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "claude-sonnet-4-20250514"
},
"options": {
"temperature": 0.4
}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "3b27dfe0-aa4e-48fa-afa8-cda6bcb0eae3",
"name": "JS - Parse AI Output & Format Listing Copy",
"type": "n8n-nodes-base.code",
"position": [
4416,
96
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const item = $input.item.json;\nlet parsed = {};\ntry {\n const rawText = item.output || item.text || item.response || '{}';\n const clean = rawText.replace(/```json|```/g, '').trim();\n parsed = JSON.parse(clean);\n} catch (e) {\n const price = item.estimatedValueFromComps || item.avgCompPrice || 0;\n parsed = {\n listingTitle: `${item.propertyType} at ${item.address}`,\n listingDescription: `This ${item.bedrooms}-bed, ${item.bathrooms}-bath ${item.propertyType.toLowerCase()} at ${item.address} has been beautifully staged in a ${item.styleApplied} style. Based on ${item.comparableCount} nearby comparables, it's priced to move.`,\n keySellingPoints: [\n `${item.squareFeet} square feet of living space`,\n `Freshly staged in a ${item.styleApplied} style`,\n `Priced using ${item.comparableCount} nearby comparable sales`\n ],\n suggestedListPrice: price\n };\n}\n\nreturn {\n json: {\n ...item,\n ...parsed\n }\n};"
},
"typeVersion": 2
},
{
"id": "fdad79b0-514a-468a-92ef-a337921190ce",
"name": "JS - Assemble Final Listing Package",
"type": "n8n-nodes-base.code",
"position": [
4816,
96
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const item = $input.item.json;\n\nconst packageGeneratedAt = new Date().toISOString();\nconst sellingPointsText = (item.keySellingPoints || [])\n .map(p => `- ${p}`)\n .join('\\n');\n\nconst listingPackageBody = `${item.listingTitle}\\nGenerated: ${packageGeneratedAt}\\n\\n${item.address}\\n${item.propertyType} | ${item.bedrooms} bed | ${item.bathrooms} bath | ${item.squareFeet} sqft\\n\\nStaged Photo: ${item.stagedImageUrl}\\n3D Walkthrough: ${item.walkthrough3dUrl}\\nStaging Style: ${item.styleApplied}\\n\\n${item.listingDescription}\\n\\nKey Selling Points:\\n${sellingPointsText}\\n\\nComp-Based Pricing (${item.comparableCount} comparables):\\nAverage Comp Price: $${item.avgCompPrice}\\nAverage Price/Sqft: $${item.avgPricePerSqft}\\nSuggested Range: $${item.suggestedPriceLow} - $${item.suggestedPriceHigh}\\n\\nSuggested List Price: $${item.suggestedListPrice}`;\n\nreturn {\n json: {\n ...item,\n packageGeneratedAt,\n listingPackageBody\n }\n};"
},
"typeVersion": 2
},
{
"id": "240c383f-da9e-43ea-bf2d-3898be7c762d",
"name": "Send Full Listing Package Email",
"type": "n8n-nodes-base.emailSend",
"position": [
5232,
96
],
"parameters": {
"options": {},
"subject": "=New Listing Ready: {{ $json.listingTitle }} - ${{ $json.suggestedListPrice }}",
"toEmail": "user@example.com",
"fromEmail": "user@example.com"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "af8ff22a-f9af-4ca2-a2bd-eec6e0815fbb",
"name": "Wait For Result",
"type": "n8n-nodes-base.wait",
"position": [
5024,
96
],
"parameters": {},
"typeVersion": 1.1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "e61fb86b-0723-4171-821e-06ea29c208a3",
"nodeGroups": [],
"connections": {
"Wait For Result": {
"main": [
[
{
"node": "Send Full Listing Package Email",
"type": "main",
"index": 0
}
]
]
},
"Anthropic - Copywriting Model": {
"ai_languageModel": [
[
{
"node": "AI - Generate Listing Copy & Price Recommendation",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Form - Upload Empty Room Photo": {
"main": [
[
{
"node": "Fetch AI Virtual Staging Render",
"type": "main",
"index": 0
},
{
"node": "Fetch Comparable Listings & Market Data",
"type": "main",
"index": 0
}
]
]
},
"Fetch AI Virtual Staging Render": {
"main": [
[
{
"node": "Merge - Combine Staging & Comps Data",
"type": "main",
"index": 0
}
]
]
},
"Wait For Staging & Comps Buffer": {
"main": [
[
{
"node": "AI - Generate Listing Copy & Price Recommendation",
"type": "main",
"index": 0
}
]
]
},
"JS - Assemble Final Listing Package": {
"main": [
[
{
"node": "Wait For Result",
"type": "main",
"index": 0
}
]
]
},
"Merge - Combine Staging & Comps Data": {
"main": [
[
{
"node": "JS - Build Property Baseline & Pricing Inputs",
"type": "main",
"index": 0
}
]
]
},
"Fetch Comparable Listings & Market Data": {
"main": [
[
{
"node": "Merge - Combine Staging & Comps Data",
"type": "main",
"index": 1
}
]
]
},
"JS - Parse AI Output & Format Listing Copy": {
"main": [
[
{
"node": "JS - Assemble Final Listing Package",
"type": "main",
"index": 0
}
]
]
},
"JS - Build Property Baseline & Pricing Inputs": {
"main": [
[
{
"node": "Wait For Staging & Comps Buffer",
"type": "main",
"index": 0
}
]
]
},
"AI - Generate Listing Copy & Price Recommendation": {
"main": [
[
{
"node": "JS - Parse AI Output & Format Listing Copy",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
anthropicApihttpHeaderAuthsmtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow collects an empty-room photo and property details via an n8n form, calls a virtual staging API and a real-estate comps API, uses Anthropic Claude to generate listing copy and a price, and emails a ready-to-publish listing package to an agent. Receives a form…
Source: https://n8n.io/workflows/17510/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow collects a user-selected financial life event through an n8n Form, retrieves account and market data, runs a Monte Carlo stress test, and uses Anthropic Claude to generate and email a pe
How it Works
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Template Nodes Example. Uses CUSTOM, formTrigger, executeWorkflowTrigger, chatTrigger. Event-driven trigger; 70 nodes.
Generate research-backed article with n8n