Mockups
Mockups
Generate lighting mockups for a project with Light AI Gen 3.0: asynchronous, 5 credits per image from the contractor's own credits.
The API generates mockups exactly as the app does, with the same model (Light AI Gen 3.0, id light-ai-gen-3.0), the same options and the same price. Finished images join the project's mockup history.
| Model | light-ai-gen-3.0 (Light AI Gen 3.0), the only model |
|---|---|
| Price | 5 credits per image, 1–4 images per generation |
| Who pays | Always the contractor, from their own credits (top-ups and Auto Top-Up work as in the app). Partners are never billed. |
| Scopes | mockups:write to generate, mockups:read to read results |
| Concurrency | At most 3 generations per organization at once |
| Test keys | Simulated: a sample image, no credits |
1. Start a generation#
By default Light AI uses the project's front view and its measured guide lines, like the app. Idempotency-Key is required: a retry with the same key returns the same generation and never charges twice.
curl -X POST "https://api.light-ai.app/v1/projects/prj_…/mockups" \
-H "Authorization: Bearer $LIGHT_AI_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"model": "light-ai-gen-3.0",
"images": 2,
"style_preset": "classic_warm_white",
"ambiance": {
"snow": true
}
}'const response = await fetch('https://api.light-ai.app/v1/projects/prj_…/mockups', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LIGHT_AI_API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body: JSON.stringify({
"model": "light-ai-gen-3.0",
"images": 2,
"style_preset": "classic_warm_white",
"ambiance": {
"snow": true
}
}),
});
const data = await response.json();import os, uuid, requests
response = requests.post(
"https://api.light-ai.app/v1/projects/prj_…/mockups",
headers={
"Authorization": f"Bearer {os.environ['LIGHT_AI_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"model": "light-ai-gen-3.0",
"images": 2,
"style_preset": "classic_warm_white",
"ambiance": {
"snow": True
}
},
)
data = response.json()The answer is 202 with a mgen_… generation in queued status. Credits are reserved now and settled per image; every failed image is refunded.
Sources#
source.type | Use |
|---|---|
front_view (default) | A front view of the project (front_view_id, default the first with a photo). Optional features limits which measured features are lit. |
photo_url | A public HTTPS photo (JPEG, PNG or WebP, at most 10 MB, no redirects), fetched once. |
photo_upload | A photo you upload: POST /v1/projects/{id}/photo_uploads, then PUT the bytes to upload_url within 2 hours. |
Options#
style_preset (classic_warm_white, cool_white, multicolor, candy_cane, red_and_green), bulb_colors (c9, mini), c9_pattern, ambiance toggles of the project's template and instructions (up to 500 characters). See the reference for every field.
2. Get the result#
Subscribe to mockup.completed and mockup.failed (they carry no image URLs), or poll:
curl "https://api.light-ai.app/v1/mockup_generations/mgen_…" \
-H "Authorization: Bearer $LIGHT_AI_API_KEY"const response = await fetch('https://api.light-ai.app/v1/mockup_generations/mgen_…', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.LIGHT_AI_API_KEY}`,
},
});
const data = await response.json();import os, requests
response = requests.get(
"https://api.light-ai.app/v1/mockup_generations/mgen_…",
headers={
"Authorization": f"Bearer {os.environ['LIGHT_AI_API_KEY']}",
},
)
data = response.json(){
"id": "mgen_3f9c2a7be41d…",
"object": "mockup_generation",
"status": "succeeded",
"model": "light-ai-gen-3.0",
"model_name": "Light AI Gen 3.0",
"images_requested": 2,
"images_succeeded": 2,
"images_failed": 0,
"images": [
{
"index": 1,
"status": "succeeded",
"mockup_id": "mk_3f9c2a7be41d…",
"url": "https://…",
"expires_at": "2026-10-12T15:03:11.000Z"
}
]
}Image URLs are signed WebP links valid for one hour; read the generation again for fresh ones. status is succeeded when at least one image succeeded and failed when none did (failure_code says why).
Credits and errors#
| Answer | Meaning |
|---|---|
402 insufficient_credits | Not enough credits. Includes required and top_up_url, plus balance for organization keys (never for partner keys). Nothing was charged. |
402 partner_spend_cap_reached | A partner key hit the spend cap the contractor set. |
429 rate_limited | Three generations already running for the organization. |
403 organization_paused | The organization is paused. |
403 organization_off_season | The organization is on Off-Season: mockups resume when the owner resumes the plan. |
Partners#
A partner can generate for a contractor only when the contractor approved mockups:write, shown on the consent screen as "Can generate mockups using your credits". Each partner has a spend cap per organization: 200 credits a day and 2,000 a month by default, which the owner can change or remove. Every API generation is labeled in the contractor's credit history and project ("Generated via API by …").