API Reference
All endpoints are relative to https://api.pixelengine.ai/functions/v1. Every request requires an API key.
/balanceReturns the authenticated user's current credit balance.
Response
{
"monthly_balance": 1200,
"purchased_balance": 500,
"total_balance": 1700,
"reserved": 20,
"available": 1680
}| Field | Type | Description |
|---|---|---|
monthly_balance | integer | Current monthly credit pool. |
purchased_balance | integer | Current purchased credit pool. |
total_balance | integer | monthly_balance + purchased_balance. |
reserved | integer | Credits held by in-flight jobs (not yet deducted). |
available | integer | Credits available for new jobs (total_balance − reserved, floor 0). |
Errors
| HTTP | Code | Cause |
|---|---|---|
| 401 | unauthorized | Invalid or inactive API key. |
/billingReturns a billing summary for the authenticated user over a given date range, plus a current balance snapshot. Useful for tracking credit spend and understanding usage over time.
Query parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
start_date | No | 30 days before end_date | Inclusive start date in YYYY-MM-DD format (UTC). |
end_date | No | Today | Inclusive end date in YYYY-MM-DD format (UTC). |
The maximum period is 365 days.
Response
{
"period": {
"start_date": "2026-03-01T00:00:00.000Z",
"end_date": "2026-03-31T23:59:59.999Z"
},
"totals": {
"credits_used": 1240,
"credits_added": 1200,
"refunds": 40,
"net_change": 0,
"jobs_charged": 62
},
"balance": {
"monthly_balance": 920,
"purchased_balance": 500,
"total_balance": 1420,
"reserved": 20,
"available": 1400
}
}| Field | Type | Description |
|---|---|---|
period.start_date | string | ISO timestamp of the period start. |
period.end_date | string | ISO timestamp of the period end. |
totals.credits_used | integer | Total credits charged (sum of debit entries). |
totals.credits_added | integer | Total credits added (purchases, monthly refresh, etc.). |
totals.refunds | integer | Total credits refunded. |
totals.net_change | integer | credits_added + refunds − credits_used. Positive means credits gained, negative means net spend. |
totals.jobs_charged | integer | Number of jobs that consumed credits in the period. |
balance | object | Current balance snapshot — same shape as GET /balance. |
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Invalid date format, start_date after end_date, or period exceeds 365 days. |
| 401 | unauthorized | Invalid or inactive API key. |
| 404 | invalid_request | No wallet found for the authenticated user. |
| 500 | internal_error | Server-side failure. |
/animateSubmits an image-to-video generation job. The endpoint supports both pixel art animation and general-purpose frame animation. Returns immediately with a job ID; generation runs asynchronously. Poll GET /jobs to track progress.
Cost: 20 credits.
Request body
{
"image": "<base64-encoded image or data URL>",
"prompt": "a character walking through a forest",
"model": "pixel-engine-v1.1",
"negative_prompt": "blurry, distorted",
"pixel_config": { "colors": 16 },
"output_frames": 8,
"seed": 12345,
"output_format": "webp",
"matte_color": "#808080"
}| Field | Type | Required | Description |
|---|---|---|---|
image | string | Yes | Base64-encoded image, or a data URL (data:image/png;base64,…). Accepted formats depend on model. See image constraints below. |
prompt | string | Yes | Non-empty text describing the desired animation. |
model | string | No | Which animation model to use. Defaults to "pixel-engine-v1.1". See Models below. |
negative_prompt | string | No | What to avoid in the generation. |
pixel_config | object | No | Pixel art color config. Defaults to { "colors": 24 }. Only allowed for "pixel-engine-v1.1". See PixelConfig below. |
output_frames | integer | No | Number of animation frames. Must be an even integer. Default: 8. Range depends on model. |
seed | integer | No | Seed for reproducibility. Integer between 1 and 9,999,999,999. If omitted, a random seed is used. |
output_format | string | No | "webp" (default), "gif", or "spritesheet". |
matte_color | string | No | 6-character hex color (e.g. "#ff0000") used to flatten any alpha channel before processing. Default: "#808080". |
Models
If model is omitted, the API defaults to "pixel-engine-v1.1".
| Model | Best for | Input formats | Image size | output_frames |
|---|---|---|---|---|
pixel-engine-v1.1 | Pixel art sprites and characters | PNG | Up to 256×256 px | 2–16 (even) |
frame-engine-v1.1 | Illustrations and non-pixel images | PNG or JPEG | 256×256 px to 2048×2048 px | 2–24 (even) |
pixel_config is rejected for "frame-engine-v1.1" with 400 invalid_request.PixelConfig
pixel_config is only valid for "pixel-engine-v1.1" (or when model is omitted, since that defaults to the pixel model). Provide one of two modes — never both. If pixel_config is omitted entirely, it defaults to count mode with 24 colors.
{ "colors": 24 }{ "palette": ["#ffaa00", "#223344", "#ffffff"] }| Field | Type | Constraints |
|---|---|---|
colors | integer | 2–256. |
palette | string[] | Array of hex color strings (e.g. "#ff0000") |
colors).Image constraints
Data URL prefixes are stripped automatically.
- Max decoded size: 5 MB for both models.
- Aspect ratio: Between 1:2 and 2:1 for both models.
- Alpha: flattened onto
matte_colorbefore processing.
| Model | Format | Dimensions | Notes |
|---|---|---|---|
pixel-engine-v1.1 | PNG only | Each axis must be 256 px or smaller | Designed for pixel art input. |
frame-engine-v1.1 | PNG or JPEG | Each axis must be between 256 px and 2048 px | Both width and height must be at least 256 px. |
output_frames must be an even integer starting at 2. The maximum is 16 for "pixel-engine-v1.1" and 24 for "frame-engine-v1.1".
Response
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "queued",
"error": null
}Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Missing or invalid field (prompt, image format, output_frames, etc.). |
| 400 | image_too_large | Image exceeds 5 MB decoded. |
| 401 | unauthorized | Invalid or inactive API key. |
| 402 | insufficient_credits | Not enough available credits. |
| 405 | method_not_allowed | Request method is not POST. |
| 500 | internal_error | Server-side failure. |
Common validation failures include unsupported image formats for the chosen model, pixel_config being sent with "frame-engine-v1.1", images smaller than 256×256 px for "frame-engine-v1.1", and odd or out-of-range output_frames values.
/animate-batchSubmits 2 to 10 animation jobs in a single request. Sub-jobs run sequentially on a single warm GPU container, sharing the cold-start cost. Returns immediately with one batch ID and an array of per-sub-job IDs. Poll the entire batch with GET /batch-jobs, or any individual sub-job with GET /jobs.
Cost: 20 credits for the first sub-job (the anchor), then 12 credits for each additional sub-job. The anchor charge is not refunded if the anchor sub-job fails — see Pricing below.
Request body
{
"jobs": [
{
"image": "<base64-encoded image or data URL>",
"prompt": "a character walking through a forest",
"model": "pixel-engine-v1.1",
"pixel_config": { "colors": 16 },
"output_frames": 8,
"seed": 12345
},
{
"image": "<base64>",
"prompt": "the same character running",
"model": "pixel-engine-v1.1",
"output_frames": 8
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
jobs | array | Yes | Array of 2 to 10 sub-job objects. Each entry takes the same fields as a POST /animate request body. Order is preserved — api_job_ids[i] in the response corresponds to jobs[i]. |
"pixel-engine-v1.1" or all "frame-engine-v1.1". Mixed batches are rejected with 400 invalid_request.Constraints
- Batch size: Between
2and10sub-jobs. - Same pipeline: Every sub-job's
modelmust resolve to the same pipeline (all pixel-engine OR all frame-engine). - Per-image limit: 5 MB decoded per image (same as
POST /animate). - Aggregate image limit: 30 MB total across all
jobs[i].imagevalues combined.
Pricing
The first sub-job in the batch is the anchor. The 20-credit anchor hold is captured on either "success" or "failure" — it covers the cold-start GPU time and is not refunded if the anchor sub-job fails. It is refunded only when a POST /cancel arrives before the anchor begins processing.
Sub-jobs at positions 1 and beyond cost 12 credits each and follow the standard rules: charged on "success", refunded on "failure" or "cancelled".
| Sub-jobs (N) | Total cost (all success) | vs N singles | Discount |
|---|---|---|---|
| 2 | 32 credits | 40 credits | 20% |
| 5 | 68 credits | 100 credits | 32% |
| 10 | 128 credits | 200 credits | 36% |
Formula: 20 + 12 × (N − 1) = 12N + 8 credits when every sub-job succeeds.
Response
{
"batch_id": "9b1c8f24-3e1c-4d2a-b6e8-1f1e2d3c4b5a",
"api_job_ids": [
"f47ac10b-58cc-4372-a567-0e02b2c3d479",
"a3d7c0d2-fbf1-43b6-baf8-deadbeef0001"
],
"status": "queued"
}api_job_ids[i] matches the input jobs[i]. Use GET /batch-jobs?batch_id=<batch_id> to poll every sub-job in one request, or GET /jobs?id=<api_job_id> for any individual sub-job.
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Batch size out of range, mixed pipelines, or any sub-job failed validation. Per-sub-job validation errors are prefixed with jobs[i]: to identify which sub-job is invalid. |
| 400 | image_too_large | A single sub-job's image exceeds 5 MB decoded. |
| 400 | payload_too_large | Aggregate image size across all sub-jobs exceeds 30 MB. |
| 401 | unauthorized | Invalid or inactive API key. |
| 402 | insufficient_credits | Not enough available credits to cover the full batch. |
| 405 | method_not_allowed | Request method is not POST. |
| 500 | internal_error | Server-side failure (image upload, Modal submission, or DB error). |
/keyframesSubmits a keyframe-conditioned generation job. Provide one or more reference images at specific frame positions, and the model interpolates between them to produce a full animation. Supports both pixel art and general-purpose output. Returns immediately with a job ID; generation runs asynchronously. Poll GET /jobs to track progress.
Cost: 24 credits.
Request body
{
"prompt": "a character walking cycle",
"render_mode": "pixel",
"total_frames": 8,
"frames": [
{ "index": 0, "image": "<base64>", "strength": 1.0 },
{ "index": 4, "image": "<base64>", "strength": 0.8 },
{ "index": 7, "image": "<base64>", "strength": 1.0 }
],
"negative_prompt": "blurry, distorted",
"pixel_config": { "colors": 24 },
"seed": 12345,
"output_format": "webp",
"matte_color": "#808080"
}| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Non-empty text describing the desired animation. |
render_mode | string | Yes | "pixel" or "detailed". Determines image format constraints and post-processing. See Render modes below. |
total_frames | integer | Yes | Total number of output frames. Integer between 3 and 20. |
frames | array | Yes | Between 1 and total_frames keyframe objects. Each provides a reference image at a specific position in the output sequence. |
frames[].index | integer | Yes | Frame position in the output sequence. Must be in range [0, total_frames − 1]. Each index may only appear once. |
frames[].image | string | One of | Base64-encoded image, or a data URL. Mutually exclusive with frames[].image_url. |
frames[].image_url | string | One of | HTTPS URL to download the keyframe image. Mutually exclusive with frames[].image. |
frames[].strength | number | No | Conditioning strength for this keyframe. Float between 0.0 and 1.0. Default: 1.0. |
negative_prompt | string | No | What to avoid in the generation. |
pixel_config | object | No | Pixel art color config. Defaults to { "colors": 24 }. Only allowed for render_mode: "pixel". See PixelConfig above. |
seed | integer | No | Seed for reproducibility. Integer between 1 and 9,999,999,999. |
output_format | string | No | "webp" (default), "gif", or "spritesheet". |
matte_color | string | No | 6-character hex color (e.g. "#ff0000") used to flatten any alpha channel before processing. Default: "#808080". |
Render modes
| Mode | Input formats | Image size |
|---|---|---|
pixel | PNG only | Up to 256×256 px per axis |
detailed | PNG or JPEG | 256–2048 px per axis |
pixel_config is rejected for render_mode: "detailed" with 400 invalid_request.Image constraints
Data URL prefixes are stripped automatically.
- Max per image: 10 MB decoded.
- Max total: 20 MB across all keyframes combined.
- Aspect ratio: Between 1:2 and 2:1.
- Consistency: All keyframe images must have the same dimensions.
- Alpha: flattened onto
matte_colorbefore processing.
Response
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "queued",
"error": null
}Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Missing or invalid field (prompt, render_mode, frames, dimensions, etc.). |
| 400 | image_too_large | Single image exceeds 10 MB or total exceeds 20 MB. |
| 400 | image_fetch_failed | An image_url could not be downloaded or timed out. |
| 401 | unauthorized | Invalid or inactive API key. |
| 402 | insufficient_credits | Not enough available credits. |
| 405 | method_not_allowed | Request method is not POST. |
| 500 | internal_error | Server-side failure. |
/generate-imageGenerates a still pixel-art image from a text prompt. Optionally accepts a reference image (base64 or URL) — when provided, the model edits/transforms the reference instead of generating from scratch (image-to-image). Returns immediately with a job ID; generation runs asynchronously. Poll GET /jobs to track progress and retrieve the output PNG.
Cost: Varies by model (6–36 credits). See Models below.
Request body
{
"prompt": "a knight standing in a torchlit dungeon",
"model": "nb_flash",
"pixel_config": { "colors": 24 },
"seed": 12345
}{
"prompt": "the same character, now wearing a red cape",
"model": "oai_gpt2_medium",
"image": "<base64-encoded image or data URL>",
"pixel_config": { "palette": ["#1a1a1a", "#c83232", "#f0c878", "#ffffff"] }
}| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | Non-empty text describing the desired image (or, in image-to-image mode, the desired edit). |
model | string | No | Which generation model to use. Defaults to "nb_flash". See Models below. |
pixel_config | object | Yes | Pixel art color config — required on this endpoint (all outputs are pixel art). Provide either colors or palette, never both. See PixelConfig below. |
image | string | No | Optional reference image. Base64-encoded image or a data URL (data:image/png;base64,…). PNG or JPEG. Mutually exclusive with image_url. When omitted, the request runs as text-to-image. |
image_url | string | No | HTTPS URL to download the reference image. Mutually exclusive with image. |
seed | integer | No | Seed for reproducibility. Integer between 1 and 9,999,999,999. Only honored by OpenAI models (oai_*) where supported; Google models (nb_*) accept the field but ignore it. |
image and image_url returns 400 invalid_request. Omitting both is valid — the request runs as text-to-image.Models
If model is omitted, the API defaults to "nb_flash". Cost is a flat per-model charge (no surcharge for the optional reference image).
| Model | Provider | Description | Cost |
|---|---|---|---|
nb_flash | Google (Nano Banana 2) | Default. Solid all-around; great quality for the price. | 12 credits |
nb_pro | Google (Nano Banana Pro) | Highest overall quality. | 36 credits |
oai_gpt2_low | OpenAI (GPT Image 2 — Low) | Cheap iteration for edits. | 6 credits |
oai_gpt2_medium | OpenAI (GPT Image 2 — Medium) | Solid all-around; best for edits. | 12 credits |
oai_gpt2_high | OpenAI (GPT Image 2 — High) | Top edit quality on complex prompts. | 36 credits |
PixelConfig
Required on this endpoint — every output is post-processed into pixel art. Provide one of two modes, never both.
{ "colors": 24 }{ "palette": ["#ffaa00", "#223344", "#ffffff"] }| Field | Type | Constraints |
|---|---|---|
colors | integer | 2–256. |
palette | string[] | Array of 6-character hex color strings (e.g. "#ff0000"). |
colors).Image constraints (reference image)
Only applies when image or image_url is provided. Data URL prefixes are stripped automatically.
- Format: PNG or JPEG.
- Max decoded size: 5 MB.
- image_url: Must be an HTTPS URL.
Response
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "queued",
"error": null
}Poll GET /jobs?id=<api_job_id> for status. On success, output.content_type will be "image/png" and output.metadata will contain width and height of the generated image.
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Missing or invalid field (prompt, model, pixel_config, image format, both image and image_url provided, etc.). |
| 400 | image_too_large | Reference image exceeds 5 MB decoded. |
| 400 | image_fetch_failed | image_url could not be downloaded or timed out. |
| 401 | unauthorized | Invalid or inactive API key. |
| 402 | insufficient_credits | Not enough available credits. |
| 405 | method_not_allowed | Request method is not POST. |
| 500 | internal_error | Server-side failure. |
/pixelateConverts an image to clean pixel art. Automatically detects the pixel grid, quantizes colors, and resamples the image to the detected grid resolution. Returns immediately with a job ID; processing runs asynchronously. Poll GET /jobs to track progress and retrieve the output PNG.
Cost: Free — does not deduct credits.
Request body
{
"image": "<base64-encoded image or data URL>",
"colors": 24
}| Field | Type | Required | Description |
|---|---|---|---|
image | string | Yes | Base64-encoded image, or a data URL (data:image/png;base64,…). PNG or JPEG. See image constraints below. |
colors | integer | No | Target number of colors for automatic palette extraction. Integer between 2 and 256. Default: 24. Mutually exclusive with palette. |
palette | string[] | No | Array of hex color strings (e.g. "#ffaa00") to force an exact palette. Mutually exclusive with colors. |
colors and palette are mutually exclusive. Providing both returns 400 invalid_request. If neither is provided, the API defaults to colors: 24.colors).Image constraints
Data URL prefixes are stripped automatically.
- Format: PNG or JPEG.
- Max decoded size: 10 MB.
- Max dimension: 2048 px on either axis.
- Aspect ratio: Between 1:2 and 2:1.
Response
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "queued",
"error": null
}Poll GET /jobs?id=<api_job_id> for status. On success, output.content_type will be "image/png" and output.metadata will contain width and height of the output image.
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Missing or invalid field (image format, colors out of range, etc.). |
| 400 | image_too_large | Image exceeds 10 MB decoded or 2048 px on either axis. |
| 400 | invalid_request | Both colors and palette were provided. |
| 401 | unauthorized | Invalid or inactive API key. |
| 405 | method_not_allowed | Request method is not POST. |
| 500 | internal_error | Server-side failure. |
/remove-backgroundRemoves the background from a still PNG or animated WebP, returning the same format with a transparent background. No prompt or model selection — this is a pure image-processing operation. Returns immediately with a job ID; processing runs asynchronously. Poll GET /jobs to track progress and retrieve the output.
Cost: 2 credits.
Run this endpoint after POST /animate or POST /keyframes completes to strip the background from the generated animation.
Request body
{
"image": "<base64-encoded image or data URL>",
"rmbg_alpha_threshold": 128
}| Field | Type | Required | Description |
|---|---|---|---|
image | string | One of | Base64-encoded image, or a data URL (data:image/png;base64,…). PNG or animated WebP. Mutually exclusive with image_url. |
image_url | string | One of | HTTPS URL to download the source image. Mutually exclusive with image. |
rmbg_alpha_threshold | integer | No | Hard alpha cutoff (0–255). Lower values keep more partial transparency around edges; higher values snap harder to fully opaque or fully transparent. When omitted, a source-dependent default is applied automatically. |
image or image_url must be provided. Providing both — or neither — returns 400 invalid_request.Image constraints
Data URL prefixes are stripped automatically.
- Format: PNG or WebP (still or animated WebP both supported).
- Max decoded size: 10 MB.
- Dimensions: No fixed cap. Larger inputs take longer to process.
Response
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "queued",
"error": null
}Poll GET /jobs?id=<api_job_id> for status. On success, output.content_type matches the input format — "image/png" for PNG inputs, "image/webp" for WebP inputs (animated WebP stays animated). output.metadata.rmbg_threshold reflects the threshold value that was applied.
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Missing or invalid field, both image and image_url provided, or neither provided. |
| 400 | image_too_large | Image exceeds 10 MB decoded. |
| 400 | image_fetch_failed | image_url could not be downloaded or timed out. |
| 401 | unauthorized | Invalid or inactive API key. |
| 402 | insufficient_credits | Not enough available credits. |
| 405 | method_not_allowed | Request method is not POST. |
| 500 | internal_error | Server-side failure. |
/cancelCancel a queued or in-progress job, or an entire batch. Credits held for cancelled sub-jobs are released immediately.
Cost: Free — does not deduct credits.
Request body
Provide exactly one of api_job_id or batch_id.
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}{
"batch_id": "9b1c8f24-3e1c-4d2a-b6e8-1f1e2d3c4b5a"
}| Field | Type | Required | Description |
|---|---|---|---|
api_job_id | string | One of | The api_job_id returned by POST /animate, POST /keyframes, POST /generate-image, POST /pixelate, POST /remove-background, or any sub-job ID returned by POST /animate-batch. When this ID belongs to a batch sub-job the entire batch is cancelled. |
batch_id | string | One of | The batch_id returned by POST /animate-batch. Cancels every non-terminal sub-job in the batch. |
"success" or "failure") are left as-is; their billing is unaffected. The 20-credit anchor charge is not refunded if the anchor sub-job has already started running by the time the cancel request arrives — see POST /animate-batch Pricing.{ batch_id } over { api_job_id }. If you pass a sub-job api_job_id whose own status is already terminal (e.g. that one sub-job already finished "success"), the request returns 409 even when other sub-jobs in the batch are still running. Using batch_id avoids this entirely and always cancels every non-terminal sibling.Response — single-job
Returned when the cancelled job is not part of a batch.
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "cancelled"
}Response — batch (request used batch_id)
Returned when the request body specified batch_id directly.
{
"batch_id": "9b1c8f24-3e1c-4d2a-b6e8-1f1e2d3c4b5a",
"status": "cancelled",
"cancelled_count": 7
}Response — batch (request used a sub-job api_job_id)
Returned when the request body specified api_job_id and that job belongs to a batch. Includes both the originally requested api_job_id (echoed for confirmation) and the resolved batch_id so the caller can correlate.
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"batch_id": "9b1c8f24-3e1c-4d2a-b6e8-1f1e2d3c4b5a",
"status": "cancelled",
"cancelled_count": 7
}Response fields
| Field | Type | Description |
|---|---|---|
api_job_id | string | Present in the single-job response and in the sibling-id batch response. Echoes the api_job_id from the request. |
batch_id | string | Present in both batch responses. Identifies the batch that was cancelled. |
status | string | Always "cancelled" on a successful cancel. |
cancelled_count | integer | Present in batch responses only. Number of sub-jobs that were transitioned to "cancelled" by this request. Sub-jobs that were already terminal ("success", "failure", or "cancelled") at the time of the call are not counted. 0 means the batch was already fully terminal — the request is still treated as a successful no-op. |
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Missing identifier, invalid JSON body, or both api_job_id and batch_id provided. |
| 401 | unauthorized | Invalid or inactive API key. |
| 404 | job_not_found | No job with that ID, or the job belongs to a different API key. |
| 404 | batch_not_found | No batch with that batch_id, or the batch belongs to a different API key. |
| 409 | invalid_request | The api_job_id target is itself already in a terminal state (message includes the current status). Cancels via batch_id never return 409 — an already-terminal batch is a successful no-op with cancelled_count: 0. |
| 500 | internal_error | Server-side failure. |
/enhance-promptRewrites a short user prompt into a precise animation caption optimized for the generation model. Optionally accepts a reference image — when provided, the AI identifies the character from the image rather than inventing appearance details. This is a synchronous endpoint; the result is returned directly (typically 1–3 seconds).
Cost: Free — does not deduct credits.
Request body
{
"prompt": "dash sword attack",
"image": "<base64-encoded image or data URL>",
"model": "pixel-engine-v1.1"
}| Field | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | The user's raw prompt text. May be an empty string when an image is provided. Maximum 2,000 characters. |
image | string | No | Base64-encoded image, or a data URL (data:image/png;base64,…). Accepted formats depend on model. See image constraints below. |
model | string | No | Which generation model the prompt is being written for. Defaults to "pixel-engine-v1.1". See Models below. |
prompt (non-empty string) or image must be provided.Models
The model field should match the model you intend to use with POST /animate. Image constraints are enforced per model. If omitted, defaults to "pixel-engine-v1.1".
| Model | Best for | Input formats | Image size |
|---|---|---|---|
pixel-engine-v1.1 | Pixel art sprites and characters | PNG | Up to 256×256 px |
frame-engine-v1.1 | Illustrations and non-pixel game art | PNG or JPEG | 256×256 px to 2048×2048 px |
Image constraints
Same per-model constraints as POST /animate. Data URL prefixes are stripped automatically.
- Max decoded size: 5 MB for both models.
- Aspect ratio: Between 1:2 and 2:1 for both models.
| Model | Format | Dimensions |
|---|---|---|
pixel-engine-v1.1 | PNG only | Each axis must be 256 px or smaller. |
frame-engine-v1.1 | PNG or JPEG | Each axis must be between 256 px and 2048 px. |
Response
{
"enhanced_prompt": "The character dashes forward with a burst of speed, executing a wide, sweeping sword slash that leaves a large white crescent trail."
}| Field | Type | Description |
|---|---|---|
enhanced_prompt | string | The rewritten prompt, ready to pass directly to POST /animate. Plain text, no Markdown or formatting. Typically 25–50 words. |
Behavior
When an image is provided, the model uses it as a reference for the rewritten caption. Without an image, it rewrites based on the text prompt alone. If only an image is provided, it generates a generic caption from the image.
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | Bad JSON, missing required fields, or invalid field values. |
| 400 | image_too_large | Image exceeds 5 MB decoded. |
| 401 | unauthorized | Missing, invalid, or inactive API key. |
| 502 | upstream_error | The AI returned an empty response. Retry may help. |
| 500 | internal_error | Server-side failure. |
/jobsReturns the current state of a job. On completion, includes a download URL or error details.
Query parameters
| Parameter | Required | Description |
|---|---|---|
id | Yes | The api_job_id returned by POST /animate, POST /keyframes, POST /generate-image, POST /pixelate, or POST /remove-background. |
Response
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "queued",
"progress": 0.0,
"created_at": "2026-03-02T18:00:00.000Z",
"finished_at": null,
"cancelled_at": null,
"billing": {
"credits_held": 20,
"credits_charged": 0,
"hold_status": "open"
},
"inputs": {
"prompt": "a character walking through a forest",
"negative_prompt": "",
"model": "pixel-engine-v1.1",
"pixel_config": { "colors": 16 },
"output_frames": 8,
"seed": 12345,
"output_format": "webp",
"matte_color": "#808080"
},
"output": null,
"error": null
}Status values
| Value | Meaning |
|---|---|
"queued" | Job accepted, waiting to be picked up. |
"pending" | Job is actively running. |
"success" | Generation complete. output is populated. billing.credits_charged > 0. |
"failure" | Generation failed. error is populated, hold is released. |
"cancelled" | Cancelled via POST /cancel. error is populated, hold is released. |
progress is a float 0.0–1.0. May remain 0 until the job is actively running.
cancelled_at is an ISO-8601 timestamp set when a job is cancelled via POST /cancel, otherwise null.
Batch sub-jobs
When the polled job is part of a batch (created by POST /animate-batch), the response also includes:
| Field | Type | Description |
|---|---|---|
batch_id | string | The parent batch ID. |
batch_position | integer | Zero-indexed position of this sub-job within the batch. Position 0 is the anchor. |
These fields are absent for jobs submitted via POST /animate or any other single-job endpoint. To poll an entire batch in one request, use GET /batch-jobs instead.
Billing object
Present whenever a wallet hold was created for the job. null if no hold exists.
{
"credits_held": 20,
"credits_charged": 0,
"hold_status": "open"
}| Field | Type | Description |
|---|---|---|
credits_held | integer | Credits reserved (held) for this job. |
credits_charged | integer | Credits actually charged. 0 until the hold is captured on success. |
hold_status | string | "open" (job in progress), "released" (cancelled/failed, credits returned), "captured" (charged on success), "expired" (hold timed out). |
Inputs object
Reflects the generation parameters submitted with POST /animate, POST /keyframes, POST /generate-image, POST /pixelate, or POST /remove-background. Always present. Fields match the original request body (excluding image / image_url). If seed was not provided in the original request, it will be absent here.
Output object (on success)
{
"url": "https://...",
"content_type": "image/webp",
"metadata": { ... },
"expires_at": "2026-03-03T18:00:00.000Z"
}| Field | Description |
|---|---|
url | Temporary download URL for the generated file. |
content_type | "image/webp", "image/gif", or "image/png" (spritesheet). |
metadata | Output dimensions and format details. See shapes below. |
expires_at | ISO timestamp when the output file will be permanently deleted. |
410 job_expired. The signed url is valid for 1 hour; re-poll GET /jobs to get a fresh one before it expires.Metadata shapes
{ "width": 64, "height": 64, "frame_count": 8, "fps": 8.0 }{
"width": 512,
"height": 64,
"output_format": "spritesheet",
"frame_count": 8,
"frame_w": 64,
"frame_h": 64
}Spritesheets are a single horizontal strip: width == frame_count × frame_w, height == frame_h.
Output dimensions
Output dimensions depend on whether the job runs in a pixel-art pipeline or a general-purpose pipeline, not on the output format. All formats (webp, gif, spritesheet) for a given job render at the same per-frame resolution.
| Pipeline | Used by | Output dimensions |
|---|---|---|
| Pixel art | POST /animate with "pixel-engine-v1.1"; POST /keyframes with render_mode: "pixel" | Output frames exactly match the original input image dimensions. A 64×64 input produces 64×64 frames in every format. |
| General | POST /animate with "frame-engine-v1.1"; POST /keyframes with render_mode: "detailed" | Output frames are rendered at the model's internal resolution: 640 px on the long side, with the short side scaled to preserve the input's aspect ratio (rounded to a multiple of 8 for frame-engine-v1.1, or 64 for render_mode: "detailed"). For example, a 1024×768 input produces 640×480 frames; a 1080×1920 input produces 360×640 frames. |
frame-engine-v1.1, or 20 frames at 640×640 px from render_mode: "detailed", packed horizontally as one PNG strip — can reach ~15–20 MB. Output files expire 24 hours after job creation; if you need to keep them longer, download and store them on your own infrastructure before the expires_at timestamp.Error object (on failure)
{
"code": "generation_failed",
"message": "Generation failed"
}Error object (on cancel)
{
"code": "job_cancelled",
"message": "Job was cancelled"
}Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | id query parameter missing. |
| 401 | unauthorized | Invalid or inactive API key. |
| 404 | job_not_found | No job with that ID, or the job belongs to a different API key. |
| 410 | job_expired | Job output has been deleted. Outputs are retained for 24 hours. |
| 500 | internal_error | Server-side failure. |
/batch-jobsReturns the current state of every sub-job in a batch in one request, ordered by batch_position. Use this instead of polling each sub-job individually with GET /jobs. Output URLs and error envelopes are included as soon as each sub-job finalizes.
Query parameters
| Parameter | Required | Description |
|---|---|---|
batch_id | Yes | The batch_id returned by POST /animate-batch. |
Response
{
"batch_id": "9b1c8f24-3e1c-4d2a-b6e8-1f1e2d3c4b5a",
"batch_size": 3,
"summary": {
"queued": 0,
"pending": 1,
"success": 1,
"failure": 1,
"cancelled": 0
},
"sub_jobs": [
{
"api_job_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"batch_position": 0,
"status": "success",
"progress": 1.0,
"created_at": "2026-03-02T18:00:00.000Z",
"finished_at": "2026-03-02T18:01:30.000Z",
"cancelled_at": null,
"billing": {
"credits_held": 20,
"credits_charged": 20,
"hold_status": "captured"
},
"inputs": { "prompt": "...", "model": "pixel-engine-v1.1", "output_frames": 8 },
"output": {
"url": "https://...",
"content_type": "image/webp",
"metadata": { "width": 64, "height": 64, "frame_count": 8, "fps": 8.0 },
"expires_at": "2026-03-03T18:00:00.000Z"
},
"error": null
},
{
"api_job_id": "a3d7c0d2-fbf1-43b6-baf8-deadbeef0001",
"batch_position": 1,
"status": "pending",
"progress": 0.4,
"created_at": "2026-03-02T18:00:00.000Z",
"finished_at": null,
"cancelled_at": null,
"billing": {
"credits_held": 12,
"credits_charged": 0,
"hold_status": "open"
},
"inputs": { "prompt": "...", "model": "pixel-engine-v1.1", "output_frames": 8 },
"output": null,
"error": null
},
{
"api_job_id": "b4e8d1e3-abcd-4321-9876-deadbeef0002",
"batch_position": 2,
"status": "failure",
"progress": 0.0,
"created_at": "2026-03-02T18:00:00.000Z",
"finished_at": "2026-03-02T18:02:10.000Z",
"cancelled_at": null,
"billing": {
"credits_held": 12,
"credits_charged": 0,
"hold_status": "released"
},
"inputs": { "prompt": "...", "model": "pixel-engine-v1.1", "output_frames": 8 },
"output": null,
"error": {
"code": "generation_failed",
"message": "Generation failed"
}
}
]
}Top-level fields
| Field | Type | Description |
|---|---|---|
batch_id | string | The batch identifier from the original request. |
batch_size | integer | Number of sub-jobs in this batch. Equal to sub_jobs.length. |
summary | object | Per-status counts — queued, pending, success, failure, cancelled. Sums to batch_size. Useful for deciding whether the batch is "done" without iterating over sub_jobs. |
sub_jobs | array | Per-sub-job entries, ordered by batch_position ascending. Each entry has the same shape as GET /jobs, minus the standalone batch_id wrapper field (the parent batch_id is on the top level instead). |
Sub-job fields
Each entry in sub_jobs mirrors a GET /jobs response — see GET /jobs for the full schema (status values, billing object, output object, error envelopes, metadata shapes). Differences:
batch_positionis always present (it is only conditional onGET /jobs).- The wrapper
batch_idfield on each sub-job is omitted to avoid repeating it on every entry — it appears once at the top level instead. - Sub-jobs whose output has been cleaned up (24-hour retention) return
output: nulland anerrorenvelope with codejob_expired, rather than failing the entire batch response.
Errors
| HTTP | Code | Cause |
|---|---|---|
| 400 | invalid_request | batch_id query parameter missing. |
| 401 | unauthorized | Invalid or inactive API key. |
| 404 | batch_not_found | No batch with that batch_id, or the batch belongs to a different API key. |
| 405 | method_not_allowed | Request method is not GET. |
| 500 | internal_error | Server-side failure. |
See also
The Introduction covers everything needed before making your first request: base URL, authentication and API key management, the credit system, the shared error response format, and the recommended polling pattern for async jobs.