API Reference
Errors
The single Clipia API error format — type, code and message fields, the table of HTTP statuses and codes, what to retry, and how to read message.
Every REST API error uses the same format: an error object with type, code and message fields. The HTTP status sets the error class; code is the machine-readable reason. Only transient errors are worth retrying after a pause: 409 request_in_progress, 429, 500 and 503.
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid or revoked API key."
}
}Branch on code. The message field is meant for humans and can change. For 400 invalid_request, message carries a short detail such as prompt_required or webhook_url_invalid; the full list for generation submit is on Submit a generation. Most messages come in English, but some input-check refusals (for example, a prompt that is too short or incompatible references) come in Russian regardless of the header. For 402 errors and music-settings refusals, the Accept-Language: ru header switches the text to Russian.
Sometimes error includes retry_after_ms or retry_after_seconds — a hint for when to retry.
Responses that never reach a route handler use the same format: 400 invalid_request for a body that is not valid JSON, 415 unsupported_media_type for a body type the server doesn't parse (for example, application/xml), 413 request_too_large for a body over 10 MB and 404 not_found for an unknown path under /v1/ (including a preflight OPTIONS from a disallowed origin). These responses never expose internal server paths.
Codes
| HTTP | code | type | When | Retry |
|---|---|---|---|---|
400 | invalid_request | invalid_request_error | invalid body, parameters or ID; the reason is in message | no, fix the request |
401 | invalid_api_key | authentication_error | the key is missing, wrong, revoked or expired | no |
402 | insufficient_credits | billing_error | not enough credits | after topping up |
402 | subscription_required | billing_error | an active subscription is required: the Public API condition for live keys, or credits frozen until the plan is renewed | after subscribing |
402 | insufficient_quota | billing_error | the request doesn't fit the key's budget, see Managing keys | once there is room in the budget |
403 | insufficient_scope | permission_error | the key lacks the required permission | no |
404 | not_found | invalid_request_error | no such model (model_not_found) or request (request_not_found) | no |
409 | idempotency_key_reuse | idempotency_error | the same Idempotency-Key with a different body | no, change the key |
409 | request_in_progress | idempotency_error | a retry while the first request is still being processed | yes, in a few seconds |
422 | model_input_invalid | invalid_request_error | the parameters don't fit the model | no, fix input |
429 | rate_limit_exceeded | rate_limit_error | request rate limit exceeded | yes, after Retry-After |
429 | concurrency_limit_exceeded | rate_limit_error | concurrent generation limit exceeded, if one is set; retry_after_seconds: 5 and Retry-After: 5 | yes, once a job finishes |
500 | internal_error | api_error | internal error | yes, with growing pauses |
503 | service_unavailable | api_error | service temporarily unavailable | yes, with growing pauses |
AI Gateway errors (/v1/chat/completions and related endpoints) use the OpenAI format; their codes are listed on Chat Completions.
A live key requires an active subscription
Generation with a clipia_live_ key works only while the account has an active subscription on clipia.ai; a clipia_test_ key works without payment. Without a subscription, submit returns 402 subscription_required: buying a credit pack without a subscription does not unlock access, a plan is required. To check ahead: GET /v1/account shows the balance, and a cost estimate never returns 402 — it computes the price without checking payment.
Two responses outside the common format
The response to a body that cannot be parsed as JSON (400) and to an unknown route (404) is not wrapped in the error envelope; it looks like { "statusCode", "timestamp", "path", "message" }. Check the HTTP status before reading error.code.
Retries
What to retry
Retry 429, 500 and 503 with growing pauses: 1, 2, 4, 8 seconds, at most 5 attempts. For 429, wait as long as Retry-After says. Retry a generation submit with the same Idempotency-Key so the retry doesn't create a second job. Other 4xx errors, apart from 409 request_in_progress and 429, come back unchanged if you resend the same request.
No internal details
Error messages don't reveal internal infrastructure. For 500 and 503 the text is generic: "An internal error occurred. Please retry or contact support." and "Service temporarily unavailable. Please retry later."
A failed generation is not an HTTP error: the result request returns 200 with status: "FAILED" and an error object whose code comes from a separate dictionary (generation_failed, content_moderated, model_unavailable and others), and the credits go back to your balance. See Result.
Rate limits
Clipia API rate limits — 120 requests per minute per key and 600 per account, RateLimit-* headers, the 429 response, concurrency limits and LLM limits.
Managing keys
How to create and revoke an API key in the Developer Console, what a new key comes with, where to find its webhook secret, and how many keys you can hold.