Image Generation Jobs
Server-side image generation runs asynchronously. You submit a batch of posts with prompts, and VoxBurst processes each one in the background using the configured AI image provider. Results are written back to the post record when ready.
Base URL
https://api.voxburst.io/v1/ai/image-jobsHow It Works
- Submit a job with up to 50 posts — each with a prompt, optional persona, and optional style settings.
- VoxBurst reserves credits immediately (1 per post item) and returns a
jobId. - Each item is processed asynchronously. Poll
GET /v1/ai/image-jobs/:jobIduntilstatusisCOMPLETED,FAILED, orCANCELLED. - Completed items contain an
imageUrland amediaIdpointing to the generated image in your workspace media library. - Failed items show an
errorCodeand can be retried individually (up to 3 attempts per item).
Job Lifecycle
PENDING → PROCESSING → COMPLETED
↓
PARTIAL (some items failed, job still ran to completion)
↓
CANCELLING → CANCELLEDItem Lifecycle
PENDING → PROCESSING → COMPLETED
↓
FAILED (retryEligible: true if under the 3-attempt limit)
↓
CANCELLED (job was cancelled before this item ran)Credits
- 1 credit is reserved per item at job submission time.
- Credits are captured (consumed) on successful item completion.
- Credits are released (refunded) for any item that fails permanently or is cancelled.
- The net charge is:
completedItems × 1 credit.
Credits are checked against your account balance at submission time. If the balance is insufficient for the full batch, the job is rejected — no partial reservations are made.
Submit a Job
POST /v1/ai/image-jobs
Creates a job and reserves credits. Returns immediately with status: PENDING.
Requires: Sufficient AI credit balance (checked at submission time — no plan gate)
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
posts | array | Yes | Items to generate (1–50) |
posts[].postId | string | Yes | ID of the post to associate the generated image with |
posts[].promptText | string | Yes | Image generation prompt (max 32,000 chars) |
posts[].style | string | No | Style modifier (max 200 chars) |
posts[].provider | string | No | Override the default image provider for this item |
posts[].personaId | string | No | Persona to apply for brand-consistent generation |
posts[].engineRules | string | No | Custom engine rule overrides (max 60,000 chars) |
posts[].negativePrompts | string[] | No | Up to 100 negative prompt strings (max 200 chars each) |
posts[].emblemRendering | "include" | "exclude" | null | No | Whether to include or suppress emblem/logo elements |
options | object | No | Job-level options passed through to the generation worker |
curl -X POST https://api.voxburst.io/v1/ai/image-jobs \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"posts": [
{
"postId": "clx_post_abc123",
"promptText": "A vibrant aerial shot of downtown Chicago at golden hour",
"style": "cinematic",
"personaId": "pp_xyz456"
},
{
"postId": "clx_post_def456",
"promptText": "Minimalist product shot of running shoes on white background",
"negativePrompts": ["cluttered", "shadows", "text"]
}
]
}'Response (201)
{
"jobId": "clx_job_abc123",
"totalItems": 2,
"status": "PENDING",
"provider": "openai",
"model": "dall-e-3",
"backupProvider": "fal",
"backupModel": null
}| Field | Description |
|---|---|
jobId | Use this to poll status and cancel the job |
provider / model | Primary AI provider configured for image generation |
backupProvider / backupModel | Fallback provider used if the primary fails |
Error (402) — Insufficient Credits
{
"error": "INSUFFICIENT_CREDITS",
"code": "INSUFFICIENT_CREDITS",
"creditsNeeded": 2,
"creditsAvailable": 0,
"message": "Insufficient AI credits: need 2, available 0"
}Get Job Status
GET /v1/ai/image-jobs/:jobId
Returns the full job record including all item statuses. Use this to poll for completion.
Recommended polling interval: 2–5 seconds.
curl https://api.voxburst.io/v1/ai/image-jobs/clx_job_abc123 \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response (200)
{
"jobId": "clx_job_abc123",
"status": "PROCESSING",
"totalItems": 2,
"completedItems": 1,
"failedItems": 0,
"cancelledItems": 0,
"createdAt": "2026-05-05T10:00:00.000Z",
"startedAt": "2026-05-05T10:00:02.000Z",
"completedAt": null,
"items": [
{
"id": "clx_item_111",
"postId": "clx_post_abc123",
"status": "COMPLETED",
"promptText": "A vibrant aerial shot of downtown Chicago at golden hour",
"resolvedPrompt": "A vibrant aerial shot of downtown Chicago at golden hour, cinematic style",
"imageUrl": "https://cdn.voxburst.io/media/img_abc123.jpg",
"mediaId": "clx_media_abc123",
"attemptCount": 1,
"retryEligible": false,
"errorCode": null,
"errorMessage": null,
"startedAt": "2026-05-05T10:00:03.000Z",
"completedAt": "2026-05-05T10:00:08.000Z"
},
{
"id": "clx_item_222",
"postId": "clx_post_def456",
"status": "PROCESSING",
"promptText": "Minimalist product shot of running shoes on white background",
"resolvedPrompt": null,
"imageUrl": null,
"mediaId": null,
"attemptCount": 1,
"retryEligible": false,
"errorCode": null,
"errorMessage": null,
"startedAt": "2026-05-05T10:00:09.000Z",
"completedAt": null
}
]
}Item Fields
| Field | Description |
|---|---|
status | PENDING | PROCESSING | COMPLETED | FAILED | CANCELLED |
resolvedPrompt | Final prompt sent to the AI provider (after persona and engine rule expansion) |
imageUrl | Public URL of the generated image — only present when status: COMPLETED |
mediaId | ID of the media record in your workspace library |
attemptCount | Number of generation attempts made (starts at 0 before first attempt) |
retryEligible | true if the item failed and has remaining attempts (< 3 total) |
errorCode | Machine-readable error code when status: FAILED |
errorMessage | Human-readable error detail |
Terminal Job Statuses
| Status | Meaning |
|---|---|
COMPLETED | All items finished (some may have failed — check failedItems) |
FAILED | Job encountered an unrecoverable error |
CANCELLED | Job was cancelled via POST /cancel |
List Active Jobs
GET /v1/ai/image-jobs
Returns up to 10 active (non-terminal) jobs for the workspace. Useful for recovering state after a client restart.
curl https://api.voxburst.io/v1/ai/image-jobs \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response (200)
{
"jobs": [
{
"jobId": "clx_job_abc123",
"status": "PROCESSING",
"totalItems": 2,
"completedItems": 1,
"failedItems": 0,
"cancelledItems": 0,
"createdAt": "2026-05-05T10:00:00.000Z",
"startedAt": "2026-05-05T10:00:02.000Z",
"completedAt": null
}
]
}Active statuses returned: PENDING, PROCESSING, PARTIAL, CANCELLING. Terminal jobs (COMPLETED, FAILED, CANCELLED) are excluded.
Cancel a Job
POST /v1/ai/image-jobs/:jobId/cancel
Signals the job to stop processing. Items that are already in-flight may still complete. Unreserved credits for pending items are returned to your balance.
curl -X POST https://api.voxburst.io/v1/ai/image-jobs/clx_job_abc123/cancel \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response (200)
{
"jobId": "clx_job_abc123",
"status": "CANCELLING"
}The job transitions to CANCELLING immediately and to CANCELLED once the worker acknowledges it.
Error (409) — Already Terminal
{ "error": "JOB_ALREADY_TERMINAL" }Returned when the job is already COMPLETED, FAILED, or CANCELLED.
Retry a Failed Item
POST /v1/ai/image-jobs/:jobId/items/:itemId/retry
Re-queues a single failed item. Each item can be attempted up to 3 times total across the original attempt and any retries. Costs 1 credit per retry (reserved immediately).
Only items with status: FAILED and retryEligible: true can be retried.
curl -X POST \
https://api.voxburst.io/v1/ai/image-jobs/clx_job_abc123/items/clx_item_222/retry \
-H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"Response (200)
{
"itemId": "clx_item_222",
"status": "PENDING"
}Poll GET /v1/ai/image-jobs/:jobId to track the item’s progress.
Errors
| Code | HTTP | Description |
|---|---|---|
ITEM_NOT_FAILED | 422 | Item is not in FAILED status |
MAX_ATTEMPTS_REACHED | 422 | Item has already been attempted 3 times |
JOB_CANCELLED | 422 | Cannot retry items in a cancelled or cancelling job |
INSUFFICIENT_CREDITS | 402 | Not enough credits to reserve for the retry |
Integration Example
async function generateImages(posts: Array<{ postId: string; promptText: string }>) {
const BASE = 'https://api.voxburst.io/v1'
const AUTH = { Authorization: 'Bearer vb_live_xxxxxxxxxxxxx' }
// 1. Submit the job
const job = await fetch(`${BASE}/ai/image-jobs`, {
method: 'POST',
headers: { ...AUTH, 'Content-Type': 'application/json' },
body: JSON.stringify({ posts }),
}).then(r => r.json())
if (job.error) throw new Error(job.message ?? job.error)
const { jobId } = job
// 2. Poll until terminal
while (true) {
await new Promise(r => setTimeout(r, 3000))
const status = await fetch(`${BASE}/ai/image-jobs/${jobId}`, {
headers: AUTH,
}).then(r => r.json())
const terminal = ['COMPLETED', 'FAILED', 'CANCELLED']
if (terminal.includes(status.status)) {
return status
}
}
}Error Codes
| Code | HTTP | Description |
|---|---|---|
INSUFFICIENT_CREDITS | 402 | Not enough credits at submission or retry time |
VALIDATION_ERROR | 400 | Request body failed schema validation — see details for field errors |
NOT_FOUND | 404 | Job or item not found, or does not belong to this workspace |
JOB_ALREADY_TERMINAL | 409 | Cancel attempted on a job that has already finished |
ITEM_NOT_FAILED | 422 | Retry attempted on a non-failed item |
MAX_ATTEMPTS_REACHED | 422 | Item has reached the 3-attempt limit |
JOB_CANCELLED | 422 | Retry attempted on a cancelled or cancelling job |