API Reference
Submit a generation
POST /v1/models/{model} — enqueue an image, video or audio generation, get a request_id, and send the request straight from this page.
Enqueue an image, video or audio generation. Fill in the parameters below and send the request with your key.
Playground
Use a test key here
Paste a clipia_test_… key into the form below: it charges no credits and calls no models, and the response has the same shape. The form keeps the key in this browser, so never enter a live clipia_live_… key here: it is a server-side secret. See Sandbox.
AuthorizationBearer <token>API key in the Authorization header with the Bearer scheme, the primary form. Generated clients add the Bearer prefix themselves, and in the playground the field already contains it: type the key after it. The playground keeps the key in this browser, so use a test key for trials:
Authorization: Bearer <CLIPIA_API_KEY>The same key is also accepted with the Key scheme (Authorization: Key <key>, the word Key in any case) and in the separate X-Api-Key header (the apiKeyHeader scheme); use whichever form suits you, the server tells them apart. The key is created in the developer console (clipia.ai/developer, "API keys" tab) and shown only once. Format: clipia_live_… (live), clipia_test_… (sandbox).
Sandbox / test mode. A key with the clipia_test_… prefix works in the sandbox: submit charges no credits and starts no real generation; it instantly returns status: COMPLETED with a deterministic mock result (a fixed sample asset on media.clipia.ai). The cost field shows the estimated cost, but it is not charged. Webhooks arrive through the same signed mechanism (HMAC-SHA256). This mode is meant for debugging an integration before you switch to a live key.
model*stringModel slug, e.g. nano-banana-2, seedance-2-fast-i2v. List: GET /v1/models.
Namespaced slugs (google/imagen4, grok-imagine/text-to-video) are passed as is (/v1/models/google/imagen4) or with %2F.
^[a-z0-9][a-z0-9-]{0,200}(?:/[a-z0-9][a-z0-9-]{0,200})?$Idempotency-Key?stringKey of a logical request for safe POST retries, up to 255 characters; a UUID v4 is recommended. A retry with the same key and the same parameters returns the stored response with no second charge and with the Idempotent-Replayed: true header. Retention: 24 hours. The same key with different parameters → 409.
length <= 255application/json- body
input*Generation parameters. The set depends on the model; see the exact schema in GET /v1/models/{model} (input_schema). Common keys: prompt, image_url, image_urls, aspect_ratio, duration, resolution, but each model has its own set: a key the model neither declares nor reads is not applied and is returned in the response warnings.
webhook_url?stringURL for a POST notification when the generation completes (optional).
uriThe generation has been accepted and queued.
application/json- response
request_id*stringGeneration request ID.
uuidstatus*GenerationStatusGeneration status in the queue. CANCELED is terminal: a generation can be canceled outside the public API (for example, from the Clipia web interface); the public API has no cancel endpoint, but status can return CANCELED, so the client must treat it as final.
"IN_QUEUE""IN_PROGRESS""COMPLETED""FAILED""CANCELED"queue_position?integerDeprecatedDeprecated: always 0, the queue position is not computed. The field stays for compatibility; rely on status and progress.
status_url*stringLink for checking the status.
uriresponse_url*stringLink for getting the result.
uricost*numberFixed operation cost in credits (reserved on submit).
warnings?array<>input parameters the model will not apply: one item per key, at most 20 items. The field is present only when such parameters exist.
items <= 20curl -X POST "https://example.com/v1/models/nano-banana-2" \ -H "Content-Type: application/json" \ -d '{ "input": { "prompt": "a sunset over mountains, cinematic", "aspect_ratio": "16:9" }, "webhook_url": "https://your-server.com/clipia/webhook" }'{ "request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b", "status": "IN_QUEUE", "queue_position": 0, "status_url": "https://api.clipia.ai/v1/requests/764cabcf-b745-4b3e-ae38-1200304cf45b/status", "response_url": "https://api.clipia.ai/v1/requests/764cabcf-b745-4b3e-ae38-1200304cf45b", "cost": 12}POST /v1/models/:model enqueues a generation and immediately returns a request_id, links to its status and result, and the reserved cost in credits. The key needs the generate permission.
/v1/models/:modelRequest
Path parameter
Prop
Type
Headers
Prop
Type
Body
Prop
Type
Common keys inside input: prompt, image_url, image_urls, aspect_ratio, duration, resolution — but every model has its own set: pass what the model declares in input_schema (what happens to an extra key is below). If the model works from a source image or video, prompt is optional; otherwise it is required.
Example
curl -X POST https://api.clipia.ai/v1/models/nano-banana-2 \
-H "Authorization: Bearer $CLIPIA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8f3a1c7e-2b4d-4e6f-9a01-23456789abcd" \
-d '{
"input": {
"prompt": "a sunset over mountains, cinematic",
"aspect_ratio": "16:9"
},
"webhook_url": "https://your-server.com/clipia/webhook"
}'Response 200
{
"request_id": "764cabcf-b745-4b3e-ae38-1200304cf45b",
"status": "IN_QUEUE",
"queue_position": 0,
"status_url": "https://api.clipia.ai/v1/requests/764cabcf-b745-4b3e-ae38-1200304cf45b/status",
"response_url": "https://api.clipia.ai/v1/requests/764cabcf-b745-4b3e-ae38-1200304cf45b",
"cost": 12
}Response fields
Prop
Type
The credits in cost are reserved on submit, charged on success, and refunded in full if the generation fails. To see the price up front, call cost estimation with the same input.
Retries
With an Idempotency-Key header, repeating the same body within 24 hours returns the same job without a second charge. Without the header, identical requests that arrive within 20 seconds are also merged into one job. In both cases the replayed response carries the Idempotent-Replayed: true header. See Idempotency.
Ignored parameters
Every model has its own set of parameters. If input contains a key the model will not apply — a typo, a parameter of another model, a key from an outdated example — the request is accepted as before and is not rejected. The response, however, also carries a warnings array with one entry per such key:
{
"request_id": "5b0c1f7e-2a53-4a0e-9d0b-6f1f4d0f2c11",
"status": "IN_QUEUE",
"queue_position": 0,
"status_url": "https://api.clipia.ai/v1/requests/5b0c1f7e-2a53-4a0e-9d0b-6f1f4d0f2c11/status",
"response_url": "https://api.clipia.ai/v1/requests/5b0c1f7e-2a53-4a0e-9d0b-6f1f4d0f2c11",
"cost": 12,
"warnings": [
{
"code": "unsupported_parameter",
"parameter": "duration",
"message": "Parameter \"duration\" is not supported by model \"nano-banana-2\" and was ignored. Parameters declared by this model: aspect_ratio, prompt, resolution. Full schema: GET /v1/models/nano-banana-2."
}
]
}Prop
Type
- When every parameter is accepted, the response has no
warningsfield. The array holds at most 20 entries. - Another spelling of a declared parameter that the server maps to the right name itself is not a warning.
- A warning appears only where the server is certain the parameter will not be applied. Its absence does not confirm that every parameter took effect: check
inputagainst the model'sinput_schema. - The same
warningsare returned by the cost estimate, by a test key, and by a retry with the sameIdempotency-Key. - In MCP the same situation is a refusal before the generation starts: see MCP tools.
Submit errors
Errors use the common {"error": {"type", "code", "message"}} format — see Errors. For 400 errors, the specific reason is in the message field.
| HTTP | code | message | When |
|---|---|---|---|
| 400 | invalid_request | invalid_model | the slug doesn't match the format: lowercase letters, digits, hyphens |
| 400 | invalid_request | prompt_required | no prompt and no source image or video |
| 400 | invalid_request | input_too_large / input_too_deep | input exceeds 100,000 bytes or 8 levels of nesting |
| 400 | invalid_request | idempotency_key_too_long | Idempotency-Key is longer than 255 characters |
| 400 | invalid_request | webhook_url_invalid | webhook_url isn't HTTPS or points to an internal address |
| 400 | invalid_request | Too many media URLs… / Too many items in <field>… | more than 30 source file URLs in one list or more than 60 distinct URLs in the request — rejected before the addresses are checked and credits are reserved |
| 400 | invalid_request | media_url_invalid | a source file URL points to an internal address or uses a scheme other than http(s). For HeyGen Video the server copies files from external URLs into its own storage before reserving credits; if a file can't be downloaded or has the wrong type or size, the message names the field and the reason: media_url_invalid: <field>: <reason> |
| 400 | invalid_request | num_images greater than 1 is not supported: send one request per image. | input contains num_images greater than 1 — one job produces one image |
| 400 | invalid_request | text naming the model limit | the narration text is shorter or longer than the model's text_limits; no credits are reserved |
| 402 | insufficient_credits | — | not enough credits |
| 402 | subscription_required | — | an active subscription is required: both the Public API condition for live keys and credits frozen until the plan is renewed |
| 402 | insufficient_quota | — | this submit would take the key's spending over its budget, see Managing keys |
| 403 | insufficient_scope | — | the key lacks the generate permission |
| 404 | not_found | model_not_found | no model with this slug, or it isn't available |
| 409 | request_in_progress / idempotency_key_reuse | — | see Idempotency |
| 429 | rate_limit_exceeded / concurrency_limit_exceeded | — | see Rate limits |
| 503 | service_unavailable | — | for HeyGen Video the server can't copy files from external URLs right now; no credits are reserved, retry after a pause |
Generation queue
How the Clipia REST API async queue works — submitting a job, polling status, fetching results, and webhooks for image, video and audio generation.
Request status
GET /v1/requests/{request_id}/status — a lightweight check of a generation's status and progress by request_id. No extra key permission is needed.