API documentation
Use the API to generate staged room photos, edit existing images, check credits, download generated assets, and receive webhooks when work is completed. Create API keys and webhook endpoints from the API Access page.
Base URL and authentication
All API requests are authenticated with an API key in the x-api-key header. API keys are scoped to the account that created them. Generated image download URLs also require the same header.
curl https://roomstack.io/api/v1/credits \ -H "x-api-key: aptd_YOUR_KEY"
Endpoints
/api/v1/generateGenerate furnished room images from one uploaded room photo.
/api/v1/editEdit an existing image with a prompt, selected furniture, or an optional mask.
/api/v1/images/{imageId}Download a generated image returned in API responses or webhook payloads.
/api/v1/creditsReturn remaining credits and current subscription state.
/api/v1/usageReturn API usage counters for the authenticated API key.
Generate room images
Send multipart form-data with one required room image. Furniture reference images are optional. Credits are charged per variant and can cost more for wider scale or larger output sizes. By default the response is synchronous and includes base64 images plus a persisted generationId when storage succeeds. Send async=true to queue the job and receive a generationId immediately.
curl -X POST https://roomstack.io/api/v1/generate \ -H "x-api-key: aptd_YOUR_KEY" \ -F image=@/path/to/empty-room.jpg \ -F style=modern \ -F roomType=living_room \ -F budget=mid \ -F variants=4 \ -F scale=wide \ -F imageSize=1K \ -F roomFidelity=strict \ -F roomSize=small \ -F furnitureImages=@/path/to/sofa.png
curl -X POST "https://roomstack.io/api/v1/generate?async=true" \ -H "x-api-key: aptd_YOUR_KEY" \ -F image=@/path/to/empty-room.jpg \ -F style=modern \ -F roomType=living_room \ -F budget=mid \ -F variants=4
image, style, roomType, budget, variants, scale, imageSize, roomFidelity, roomSize, promptOverride, async, and repeated furnitureImages.
roomFidelity can be strict, balanced, or creative. Use strict when the room itself must not change. roomSize can be small, medium, or large to guide furniture scale.
Edit an image
Use edit when you already have a generated image or a customer-facing photo and want to adjust styling, furniture, light, or layout. Edits cost 1 credit.
curl -X POST https://roomstack.io/api/v1/edit \
-H "x-api-key: aptd_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"originalImage": "data:image/png;base64,...",
"editPrompt": "Make the room warmer and add modern Nordic furniture",
"selectedFurniture": ["oak dining table", "linen sofa"]
}'Response format
Generation and edit endpoints return the provider request id, persisted generation id, image results, and metadata. Images are returned as data URLs/base64 for immediate use. When webhooks fire, they include authenticated download URLs for the same stored images. Async generation returns HTTP 202 with status queued; poll /api/generations?id=... in the app or rely on webhooks for completion.
{
"requestId": "provider_request_id",
"generationId": "persisted_generation_id",
"images": [
{
"base64": "data:image/png;base64,..."
}
],
"meta": {
"status": "COMPLETED",
"durationMs": 8400
}
}Download generated images
Webhook payloads include downloadUrl for each generated image. Download URLs are not public; call them with your API key. This keeps webhook payloads small while still letting you copy images to your own CDN, DAM, CRM, or listing platform.
curl https://roomstack.io/api/v1/images/IMAGE_ID \ -H "x-api-key: aptd_YOUR_KEY" \ --output staged-room.png
Webhooks
Webhooks can be configured under API Access. RoomStack sends a POST request when a generation or edit completes. A webhook endpoint can subscribe to generation.completed, edit.completed, or both.
{
"id": "delivery_id",
"event": "generation.completed",
"createdAt": "2026-05-01T12:00:00.000Z",
"data": {
"generationId": "generation_id",
"kind": "generation",
"source": "api",
"status": "completed",
"creditsCharged": 1,
"settings": {
"style": "modern",
"roomType": "living_room",
"variants": 4
},
"images": [
{
"id": "image_id",
"index": 0,
"mimeType": "image/png",
"sizeBytes": 123456,
"downloadUrl": "https://roomstack.io/api/v1/images/image_id"
}
]
}
}Webhook signatures
Each delivery is signed with your endpoint secret. Verify signatures before trusting the payload. The signature base string is timestamp + "." + rawBody, signed with HMAC SHA-256.
RoomStack-EventRoomStack-DeliveryRoomStack-TimestampRoomStack-Signature
RoomStack-Signature: v1=hex_hmac_sha256
import crypto from "crypto";
function verifyRoomStackWebhook({ rawBody, timestamp, signature, secret }) {
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature.replace("v1=", ""), "hex"),
Buffer.from(expected, "hex")
);
}Errors and rate limits
- 400: invalid input or unsupported file
- 401: missing or invalid API key
- 402: not enough credits
- 403: subscription or permission issue
- 429: rate limit exceeded
- 500: provider or server error
{
"error": "Not enough credits.",
"creditsRequired": 2,
"availableCredits": 0
}