API Reference

Use the VirtualStaging.ai API to submit virtual staging, furniture removal, and custom-prompt editing jobs from your own application. All jobs are processed asynchronously — you submit a request and receive the result via a webhook callback.

Overview

Base URL

How it works

  1. You POST a request with an image URL, a webhook URL, and a payload describing the operation.
  2. The API responds immediately with a request_id and starts processing in the background.
  3. When the render is complete, the API calls your webhook with the result image URL.
  4. Each request uses 1 token from your subscription. Revisions are free.

Request headers

Both Authorization and Email are required on every request. Your API key and email are shown in Account Settings → API settings.

Authentication

Generate an API key

  1. Log in and go to Account Settings, then click the API settings tab.
  2. Click Generate key, enter a name, and confirm.
  3. Copy both the Key and the Secret immediately — the key is only visible for 1 hour and the secret is used to verify webhook callbacks.

Revoke an API key

  1. Go to the API settings tab in Account Settings.
  2. Click Revoke key next to the key you want to disable.
Security tip: never expose your API key in client-side code or public repositories. Store it as an environment variable on your server.

Endpoints

All operations share a single endpoint:

The operation type is determined by the type field inside the payload JSON string.

Virtual Staging

Virtually furnish and decorate an empty room. Choose a style and room type combination from the list of valid type values below.

Request parameters

FieldDescription
imagerequiredPublicly accessible HTTPS URL of the source room photo.
webhookrequiredHTTPS URL that receives the result callback when rendering is complete.
payloadrequiredA JSON-encoded string containing at minimum identifier and type.

Payload fields

FieldDescription
identifierrequiredYour own reference ID — echoed back in the webhook so you can match the result to your record.
typerequiredThe staging style. See valid values below.

Valid type values

StyleValid values
ModernModern LivingModern BedroomModern DiningModern OfficeModern Living & DiningModern HallwayModern Game RoomModern Kid's RoomModern Nursery
Luxury ModernLuxury Modern LivingLuxury Modern BedroomLuxury Modern DiningLuxury Modern OfficeLuxury Modern Living & DiningLuxury Modern HallwayLuxury Modern Game RoomLuxury Modern Kid's RoomLuxury Modern Nursery
ScandinavianScandinavian LivingScandinavian BedroomScandinavian DiningScandinavian OfficeScandinavian Living & DiningScandinavian HallwayScandinavian Game RoomScandinavian Kid's RoomScandinavian Nursery
IndustrialIndustrial LivingIndustrial BedroomIndustrial DiningIndustrial OfficeIndustrial Living & DiningIndustrial HallwayIndustrial Game RoomIndustrial Kid's RoomIndustrial Nursery
TraditionalTraditional LivingTraditional BedroomTraditional DiningTraditional OfficeTraditional Living & DiningTraditional HallwayTraditional Game RoomTraditional Kid's RoomTraditional Nursery
BohemianBohemian LivingBohemian BedroomBohemian DiningBohemian OfficeBohemian Living & DiningBohemian HallwayBohemian Game RoomBohemian Kid's RoomBohemian Nursery
TransitionalTransitional LivingTransitional BedroomTransitional DiningTransitional OfficeTransitional Living & DiningTransitional HallwayTransitional Game RoomTransitional Kid's RoomTransitional Nursery
Mid CenturyMid Century LivingMid Century BedroomMid Century DiningMid Century OfficeMid Century Living & DiningMid Century HallwayMid Century Game RoomMid Century Kid's RoomMid Century Nursery
FarmhouseFarmhouse LivingFarmhouse BedroomFarmhouse DiningFarmhouse OfficeFarmhouse Living & DiningFarmhouse HallwayFarmhouse Game RoomFarmhouse Kid's RoomFarmhouse Nursery

Request body

Response

Python

JavaScript (Node.js)

cURL

Multi-angle Staging

Generate a staged version of a room using two angles of the same space. Send the empty room photo you want staged as image, and include an already-staged image of the same room from another angle as ref_image inside the payload. The AI reuses the furniture, layout and style from ref_image so both angles stay consistent.

Both images must be the same physical room. First stage one angle with the standard Virtual Staging endpoint, then pass that staged result as ref_image when staging the next angle. For best consistency use overlapping angles and avoid fully opposite shots. The result is a single staged image based on image.

Request parameters

FieldDescription
imagerequiredPublicly accessible HTTPS URL of the empty room photo for the angle you want staged.
webhookrequiredHTTPS URL that receives the result callback when rendering is complete.
payloadrequiredJSON-encoded string with identifier, type, and ref_image.

Payload fields

FieldDescription
identifierrequiredYour own reference ID.
typerequiredThe staging style — same valid values as Virtual Staging.
ref_imagerequiredPublicly accessible HTTPS URL of an already-staged image of the same room from another angle (typically the output of a previous staging call).

Request body

Response

Python

JavaScript (Node.js)

cURL

Furniture Removal

Remove specific objects from a room photo using a mask image. The mask must be the same dimensions as the source image — white pixels mark areas to remove, black pixels are kept.

Request parameters

FieldDescription
imagerequiredPublicly accessible HTTPS URL of the source room photo.
maskrequiredPublicly accessible HTTPS URL of the mask image (same dimensions as image). White = remove, black = keep.
webhookrequiredHTTPS URL that receives the result callback.
payloadrequiredJSON-encoded string with identifier and type: "removal".

Request body

Python

cURL

Custom Prompt

Edit a room photo using a free-text prompt. The AI will apply the instructions to the source image. Use type: "refine" and include a prompt field in the payload.

Request parameters

FieldDescription
imagerequiredPublicly accessible HTTPS URL of the source room photo.
webhookrequiredHTTPS URL that receives the result callback.
payloadrequiredJSON-encoded string with identifier, type: "refine", and prompt.

Payload fields

FieldDescription
identifierrequiredYour own reference ID.
typerequiredMust be "refine".
promptrequiredA natural-language description of the changes to apply to the image.

Request body

Python

JavaScript (Node.js)

cURL

Revision

Re-run any previous request by sending its request_id back to the same endpoint. Revisions do not consume a token. You can revise unlimited times.

Optionally override webhook or payload on the revision if you need the result delivered to a different URL or with different metadata.

Request parameters

FieldDescription
request_idrequiredThe request_id returned by the original request.
webhookoptionalOverride the webhook URL for this revision only.
payloadoptionalOverride the payload JSON string for this revision only.

Request body (minimal)

Request body (with overrides)

Response

Python

JavaScript (Node.js)

cURL

Webhook

When a render completes, we send a POST request to your webhook URL with the result.

Webhook payload

identifier is exactly what you sent in the original request payload. Use it to match this callback to your internal record.

output is the URL of the completed render.

Verifying authenticity

Every webhook request includes a Verification-Token header set to your API key secret. Always validate this before processing the payload.

Important: webhook endpoints must allow unauthenticated access — do not protect them with standard auth middleware. Use only the token check below.

Node.js (Express)

Python (Django REST Framework)

PHP (Symfony) — security.yaml

PHP (Symfony) — Controller

Testing your credentials

Before making real requests, verify that your API key, secret, and email are configured correctly by calling the test endpoint. It does not consume a token.

POST https://backend.virtualstaging.ai:8443/api/api-test/

A successful response confirms your credentials and shows which plan is active:

If you receive 401 the key, email, or secret is wrong. Generate a new key in Account Settings → API settings.

Errors

All errors return HTTP 400 with a JSON body containing an error field.

HTTPError messageCause & fix
Authentication
401No auth token or email providedThe Authorization or Email header is missing. Both are required on every request.
401Invalid or inactive API keyThe API key does not match the email, has been revoked, or belongs to a different account. Generate a new key in Account Settings → API settings.
Tokens & requests
400No fundsNo tokens remaining on your subscription. Purchase more or upgrade your plan.
400There is no request with this idThe request_id does not exist or belongs to a different API key.
URL validation
400Image URL must use HTTPS.Only HTTPS URLs are accepted for image.
400Invalid image URL.The image field is not a valid URL.
400Image URL does not exist.The server could not reach the image. Make sure it is publicly accessible and returns HTTP 200.
400Mask URL must use HTTPS.Only HTTPS URLs are accepted for mask.
400Invalid mask URL.The mask field is not a valid URL.
400Mask URL does not exist.Make sure the mask image is publicly accessible and returns HTTP 200.
400Webhook URL must use HTTPS.Only HTTPS URLs are accepted for webhook.
400Invalid webhook URL.The webhook field is not a valid URL.
Payload validation
400Payload must be a valid JSON string.payload must be a JSON-encoded string, not a nested object. Use json.dumps() in Python or JSON.stringify() in JavaScript.
400Payload must contain a 'type' key with a valid value.The type field is missing or unrecognized. See valid type values.
400Payload must contain an 'identifier'...The identifier field is missing. It must be a string or number used to match the webhook callback to your record.

Example error response

Limits & Costs

Token costs

OperationToken cost
Virtual Staging1 token
Furniture Removal1 token
Custom Prompt1 token
Revision (any type)Free

Concurrency & throughput

  • There is no hard limit on how many requests you can submit.
  • The rendering pipeline processes approximately 2–3 jobs simultaneously.
  • Because the API is asynchronous you can submit many requests in parallel — extra jobs are queued and processed in order. Expect delays during peak demand.

Need help?

Email: [email protected]
Live chat: via Intercom on our website