• English
  • Deutsch
  • Nederlands
  • Español
  • Français
  • Italiano
  • Português
  • Русский
  • 中文
  • 日本語
  • 한국어

Stagify.ai › API documentation

Stagify API

API dashboard

Stage a real-estate photo from your own code. One HTTP call returns one staged image. Prepaid credits at $0.15 an image, with no subscription, no minimum and no bill that can run away from you.

Base URL
https://stagify.ai/api/v1
Authentication
Bearer stg_live_…
Content type
multipart/form-data

Introduction

The API exposes one thing: the staging pipeline behind the web app. You post a photo of a room, name a room type and a furniture style, and get a staged image back in the same response. There is no job queue and nothing to poll on the happy path.

Credits are whole images. You buy them up front and each successful render spends one. A render that fails is refunded automatically, so you only ever pay for a photo you received. And because the balance is prepaid, a stolen key costs you at most what is left on it. There is no invoice at the end of the month.

Keys are meant for server-to-server use. The API sends no CORS headers, so a browser cannot call it directly; that is deliberate, and a key reachable from browser JavaScript is a leaked key. We show a key once, store only a hash, and revoke immediately.

Quickstart

Create a key on your API keys page, buy a credit pack, then post a photo. The response carries the staged image as a data URL.

curl https://stagify.ai/api/v1/renders \
  -H "Authorization: Bearer $STAGIFY_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "image=@living-room.jpg" \
  -F "roomType=Living room" \
  -F "furnitureStyle=modern" \
  -F "labelVirtuallyStaged=true"

A render takes up to a couple of minutes. Set your client’s read timeout to 300 seconds and retry with the same Idempotency-Key. That is what guarantees you are never charged twice for one photo.

Credit packs

Loading pricing…

Request parameters

POST /api/v1/renders, sent as multipart/form-data. Every accepted value below is also served as JSON from GET /api/v1/options, which needs no API key, so a client can populate its own dropdowns instead of hard-coding this table.

FieldTypeNotes
imagefileRequired. The room photo. JPEG, PNG or WebP, up to 25 MB. The MIME type is what is checked, not the file extension.
roomTypeenum Bedroom, Living room, Dining room, Kitchen, Office, Bathroom, Outdoors, Dorm. Default Living room. Case- and space-sensitive, and an unrecognised value is not rejected. It is written into the prompt as free text, so Living Room is not Living room.
furnitureStyleenum standard, modern, midcentury, scandinavian, luxury, coastal, farmhouse, custom. Default standard, which is also what an unrecognised value silently becomes. custom uses your additionalPrompt in place of the built-in style text.
additionalPromptstringFree-text direction for this render.
removeFurniturebooleanEmpty the room before staging it. Send true or on; anything else, including 1 and yes, reads as false.
keepFurniturestringFree text naming what to leave in place, e.g. keep the dining table and the built-in shelves. Read only when removeFurniture is set. 500 characters.
furnitureImagefile[]Up to 5 reference photos of furniture to match. Same formats and size limit as image.
labelVirtuallyStagedbooleanBurn the “Virtually staged” disclosure onto the output.
stampStyleenum dark, light, minimal, banner. Default dark. Case-insensitive; an unrecognised value falls back to the default.
stampScalenumber 0.7 to 1.6, default 1. Out-of-range values are clamped rather than refused.
stampLangenum The badge language: english, spanish, french, german, chinese, korean, portuguese, russian, italian, japanese, dutch. Default english.
variationsintegerOnly 1 is accepted. Issue concurrent requests for more.

Idempotency

A render holds the connection for minutes, which means the failure that will actually bite you is a dead socket after the work completed: charged, holding nothing. Send an Idempotency-Key header on every request and retry with the same value.

What we have on fileWhat a retry does
A succeeded request, same parametersReturns the stored result with X-Stagify-Replayed: true. No second charge.
A request still running409 REQUEST_IN_FLIGHT. Wait, then retry.
A request abandoned mid-renderRe-runs on the existing charge, up to three attempts.
The same key with different parameters422 IDEMPOTENCY_KEY_REUSED. Use a fresh key.

Omitting the header is allowed and means no replay protection, which is the honest default. We do not derive a key from your photo: two genuinely separate renders of the same room would collide and the second caller would be handed the first one’s image.

Disclosure labels

Many MLS and NAR rules require a staged photo to say that it is staged. labelVirtuallyStaged burns that label into the pixels rather than attaching it as metadata that a downstream tool can strip.

If the label cannot be applied, the image is withheld rather than delivered unlabelled, the call answers 500 DISCLOSURE_STAMP_FAILED, and your credit is refunded. There is no way to switch that behaviour off, and no per-key default that quietly disables it.

Errors

Every failure answers { "error": "…", "code": "…" }. Branch on code, never on the message. Messages change, codes do not.

StatusCodeWhat to do
401API_KEY_MISSING / API_KEY_INVALID / API_KEY_REVOKEDCheck the Authorization header, or mint a new key.
402INSUFFICIENT_CREDITSTop up. The body carries credits_remaining.
403ACCOUNT_SUSPENDEDContact support.
400VARIATIONS_UNSUPPORTEDThis API renders one image per request. Issue concurrent requests instead.
409REQUEST_IN_FLIGHTThat idempotency key is still running. Wait, then retry.
409CONCURRENCY_LIMITToo many renders at once. Retry in a few seconds.
422IDEMPOTENCY_KEY_REUSEDYou reused a key with different parameters. Use a fresh one.
422NO_IMAGE_GENERATEDThe model returned nothing. Refunded; retry or try another photo.
429RATE_LIMITEDBack off and retry.
500DISCLOSURE_STAMP_FAILEDThe label could not be applied so the image was withheld. Refunded.
500RENDER_FAILEDRefunded. Quote the ref if you contact support.

Other endpoints

  • GET /api/v1/options: the accepted values for every enum above. No API key required.
  • GET /api/v1/me: is my key working? Returns the account and balance.
  • GET /api/v1/credits: balance and lifetime totals.
  • GET /api/v1/renders/{id}: the status of one render.

Every response carries X-Stagify-Credits-Remaining, so you can watch the balance fall without polling for it.

Questions, higher limits, or an invoice instead of a card: team@stagify.ai.