StageHQ

StageHQ API

Stage room photos from your own code. The API uses the same engine and the same credits as the studio: 1 credit per staged image, and a failed job refunds its credit. Base URL: https://stagehq.ai/api/v1.

Quickstart

  1. Buy any credit pack. API keys are for paid accounts.
  2. Open Account → Developers and create a key. Copy it: it is shown once.
  3. Send a photo, then poll the job until it is finished.
Node.js 18+
import { readFile } from "node:fs/promises";

const API = "https://stagehq.ai/api/v1";
const headers = { Authorization: `Bearer ${process.env.STAGEHQ_API_KEY}` };

const form = new FormData();
const photo = new Blob([await readFile("empty-room.jpg")], { type: "image/jpeg" });
form.append("image", photo, "empty-room.jpg");
form.append("room_type", "bedroom");
form.append("style", "scandinavian");

const submit = await fetch(`${API}/stagings`, {
  method: "POST",
  headers: { ...headers, "Idempotency-Key": "listing-1042-photo-3" },
  body: form,
});
const job = await submit.json();
if (!submit.ok) throw new Error(`${job.code}: ${job.message}`);

let gen;
do {
  await new Promise((r) => setTimeout(r, 5000));
  gen = await (await fetch(`${API}/generations/${job.id}`, { headers })).json();
} while (gen.status === "processing");

console.log(gen.status, gen.result_url);

Authentication

Send the key in the Authorization header of every request: Authorization: Bearer shq_live_…. Keys start with shq_live_. An account can have up to 5 active keys; revoke a key on the account page at any time.

Keep the key on your server. It spends your credits, so do not put it in a website, a mobile app or a public repository.

Stage a photo

POST /api/v1/stagings with a multipart/form-data body. Returns 202 with the job id and charges 1 credit.

FieldRequiredDescription
imageYesJPEG, PNG or WebP file, up to 10 MB.
room_typeNoOne of the room types. Default living room.
styleNoOne of the styles. Default modern.
modeNoOne of the modes. Default precise.
room_descriptionNoShort description of the room, up to 160 characters.
instructionsNoExtra instructions for this photo, up to 500 characters. Name positions from things in the photo ("bed against the wall with the window").

Unknown values are rejected with invalid_parameter; nothing is charged.

Request
curl https://stagehq.ai/api/v1/stagings \
  -H "Authorization: Bearer $STAGEHQ_API_KEY" \
  -H "Idempotency-Key: listing-1042-photo-3" \
  -F [email protected] \
  -F room_type=bedroom \
  -F style=scandinavian \
  -F mode=precise \
  -F room_description="corner room, two windows" \
  -F instructions="queen bed against the long wall"
Response
HTTP/1.1 202 Accepted

{
  "id": "6f1c2a7e-4b8d-4c55-9a1e-2f3b4c5d6e7f",
  "status": "processing",
  "status_url": "https://stagehq.ai/api/v1/generations/6f1c2a7e-4b8d-4c55-9a1e-2f3b4c5d6e7f",
  "credits_remaining": 41,
  "replayed": false
}

Get a job

GET /api/v1/generations/{id}. Poll every 5 seconds until status is completed or failed; most jobs finish in about 30 seconds. A job finishes on our side even if you stop polling.

Request
curl https://stagehq.ai/api/v1/generations/6f1c2a7e-4b8d-4c55-9a1e-2f3b4c5d6e7f \
  -H "Authorization: Bearer $STAGEHQ_API_KEY"
Response
{
  "id": "6f1c2a7e-4b8d-4c55-9a1e-2f3b4c5d6e7f",
  "tool": "staging",
  "status": "completed",
  "mode": "precise",
  "room_type": "bedroom",
  "style": "scandinavian",
  "source_url": "https://cdn.stagehq.ai/uploads/…/6f1c2a7e-….jpg",
  "result_url": "https://cdn.stagehq.ai/results/…/6f1c2a7e-….png",
  "error": null,
  "created_at": "2026-10-06T09:00:00.000Z",
  "completed_at": "2026-10-06T09:00:31.000Z"
}

result_url is a permanent link to the staged image at about 2K resolution. The file name contains a random token, but anyone who has the link can open the image, so treat it like a private link and copy the file into your own storage. A failed job has an error value and its credit is refunded.

Credit balance

GET /api/v1/credits returns the account balance.

curl https://stagehq.ai/api/v1/credits \
  -H "Authorization: Bearer $STAGEHQ_API_KEY"

{ "credits": 41, "plan": "paid" }

Safe retries

Send an Idempotency-Key header (1–255 printable characters, no spaces) with POST /stagings. If a request with the same key already exists on your account, the API returns that job with 200, "replayed": trueand the job's current status, and charges nothing. A repeat with different fields still returns the first job. Use one key per photo, for example your listing id plus the photo number, so a timeout retry never pays twice.

Modes

modeWhat it does
preciseDefault. Adds furniture and decor; walls, floors, windows and fixtures stay exactly as photographed.
creativeFuller styling: furniture, decor, artwork and accent finishes.
renovationShows the room remodeled: new finishes, fixtures and layout.
removeRemoves the furniture and clutter in the photo and leaves the room empty.

Room types

Grouproom_type values
Residentialliving roombedroomnurserybathroomkitchendining roomhome officestudioloftdressing roomtoiletbasementgarage
Commercialoffice spacemeeting roomcoworking spacereception area
Hospitalityhotel lobbyhotel roomhotel bathroomrestaurantcoffee shop
Specialtystudy roomgaming roomworkshopfitness gymauditoriumclassroomlecture hallclothing store
Outdoorbackyardpatio

Styles

Groupstyle values
Popularai-decidemodernminimalistcontemporaryjapandiwarm-cozymodern-farmhouse
Classicneoclassicart-decoart-nouveaubaroquemidcentury-modernbauhaus
Natural & Organicbiophilicrusticcoastalmediterraneantropicalwabi-sabizen
Bold & Eclecticindustrialboho-chiceclecticmaximalisttribal
Luxuryluxuryscandinavian
Vintage & Retrovintageshabby-chicmedievalpharaonic
Futuristicfuturisticcyberpunk
Seasonalchristmashalloween

Errors

Every error has the same JSON shape. Use code in your logic and show message to people.

HTTP/1.1 402 Payment Required

{
  "status": "error",
  "code": "insufficient_credits",
  "message": "Not enough credits. Buy credits to continue."
}
HTTPcodeMeaning
400invalid_parameterA parameter or the Idempotency-Key is not valid. The message names the field.
400image_requiredNo `image` file in the form.
400invalid_formatThe file is not a JPEG, PNG or WebP image.
400file_too_largeThe file is larger than 10 MB.
400read_errorThe image could not be decoded.
401invalid_api_keyThe key is missing, malformed, unknown or revoked.
402insufficient_creditsThe account has no credits left.
403paid_requiredThe account has no paid credit pack. Keys work only on paid accounts.
404not_foundNo job with this id on your account.
429rate_limitedToo many stagings this minute. Wait for the Retry-After seconds.
500api_errorThe job could not start. The credit was refunded; retry.

Limits

  • 12 stagings per minute per account, shared with the studio. Over the limit: 429 with a Retry-After header.
  • Polling a running job: up to 60 checks per minute per account. Over that, the response still comes back, with a Retry-After header.
  • Images: JPEG, PNG or WebP, up to 10 MB; larger than 4096 px on a side is resized down.
  • Server-to-server only: the API does not send CORS headers for browser calls.

Questions or a feature you need? Contact us.