# Errors

> Error format, what each HTTP status asks of you and the complete catalog of codes.

Every error, on every route and every status, has the same body:

```json
{ "code": "INSUFFICIENT_CREDITS", "extra": { "credits_needed": 121, "current_balance": 40 } }
```

| Field | Type | Description |
|---|---|---|
| `code` | string | Stable identifier, uppercase, from a closed set. Use a `switch` on it. |
| `extra` | object | Only appears when there is something to act on: what was missing, which field failed, which ids were rejected. |

There is no text message. The server does not know your user's language, and text cannot be handled in a `switch`: translate the `code` in your interface.

## HTTP status

| Status | Means | What to do |
|---|---|---|
| `400` | The request body is wrong | Fix it. Repeating it unchanged gives the same error. |
| `401` | Missing, revoked or expired key | Check the `X-Api-Key` header. |
| `402` | Insufficient credits | Read `extra.credits_needed` and top up. |
| `403` | The source or the account is out of reach | There is nothing to retry. |
| `404` | Does not exist in this workspace | Check the id and the workspace. |
| `409` | It exists, but its current state refuses the operation | Wait and try again. |
| `410` | It existed and expired | Upload again or render again. |
| `422` | Valid link, unusable video | Use another source. |
| `429` | Rate limit | Wait the seconds in `Retry-After`. |
| `5xx` | Our failure | Retry with increasing backoff. |

## Validation

A body or query outside the schema returns `VALIDATION_ERROR`, and `extra.errors` lists the fields that failed, with a dot between levels:

```json title="400 Bad Request"
{ "code": "VALIDATION_ERROR", "extra": { "errors": ["video_id", "timeframe.end"] } }
```

## Nonexistent route

A path that does not exist returns `404 NOT_FOUND`, with `extra.openapi` pointing to the specification and `extra.docs` to this documentation's `llms.txt`. That is how an agent that guessed the route finds the right path.

## Handling errors

**Node.js**

```js
const response = await fetch(`${API}/clips`, { method: "POST", headers, body });
if (!response.ok) {
	const { code, extra } = await response.json();
	switch (code) {
		case "INSUFFICIENT_CREDITS":
			return askForTopUp(extra.credits_needed);
		case "RATE_LIMIT_EXCEEDED":
		case "SERVICE_UNAVAILABLE":
			return retryAfter(Number(response.headers.get("Retry-After")));
		default:
			throw new Error(code);
	}
}
```

**Python**

```python
response = requests.post(f"{API}/clips", headers=HEADERS, json=body)
if not response.ok:
    error = response.json()
    match error["code"]:
        case "INSUFFICIENT_CREDITS":
            return ask_for_top_up(error["extra"]["credits_needed"])
        case "RATE_LIMIT_EXCEEDED" | "SERVICE_UNAVAILABLE":
            return retry_after(int(response.headers["Retry-After"]))
        case _:
            raise RuntimeError(error["code"])
```

## Job error

A job that fails after being accepted does not return an error HTTP status: the read route responds `200` with `status: "failed"` and the reason in `error_code`. In clipping, for example, `DOWNLOAD_PRIVATE_VIDEO` says the video became private after the analysis. See [Clipping](/en/clipping#when-it-fails).

## Code catalog

All the codes the API returns, generated from the specification on every publication of this documentation. For the meaning of a code on a route, open the route in the [reference](/reference).

| Code | Status | Returned by |
|---|---|---|
| `CONNECTION_INVALID` | 400 | `DELETE /posts/{id}/items/{itemId}` |
| `DELETE_FAILED` | 400 | `DELETE /posts/{id}/items/{itemId}` |
| `DELETE_LIMIT_REACHED` | 400 | `DELETE /posts/{id}/items/{itemId}` |
| `DELETE_NOT_SUPPORTED` | 400 | `DELETE /posts/{id}/items/{itemId}` |
| `FILE_TOO_LARGE` | 400 | `POST /videos/upload`, `POST /transcriptions/upload`, `POST /personas/sources/upload` |
| `IMAGES_INVALID` | 400 | `POST /generations` |
| `INVALID_CHANNEL_URL` | 400 | `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop` |
| `INVALID_CONNECTIONS` | 400 | `POST /posts`, `PATCH /posts/{id}` |
| `INVALID_DURATION_RANGE` | 400 | `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop` |
| `INVALID_FILE_TYPE` | 400 | `POST /videos/upload`, `POST /transcriptions/upload`, `POST /personas/sources/upload` |
| `INVALID_IMAGE` | 400 | `POST /personas/faces`, `POST /personas/{id}/shots/photos`, `POST /generations/images` |
| `INVALID_METADATA` | 400 | `POST /posts` |
| `INVALID_OBSERVING_TYPE` | 400 | `GET /monitors/{id}/broadcasts`, `GET /monitors/{id}/broadcasts/{broadcastId}/clips`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/apply_template`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render` |
| `INVALID_SCHEDULED_AT` | 400 | `POST /posts`, `PATCH /posts/{id}` |
| `INVALID_STRATEGY_OPTIONS` | 400 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `INVALID_TRANSLATE_LANGUAGE` | 400 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `ITEM_NOT_EDITABLE` | 400 | `PATCH /posts/{id}` |
| `ITEM_NOT_FAILED` | 400 | `POST /posts/{id}/items/{itemId}/retry` |
| `ITEM_NOT_REMOVABLE` | 400 | `DELETE /posts/{id}/items/{itemId}` |
| `ITEMS_EMPTY` | 400 | `PATCH /posts/{id}` |
| `MEDIA_METADATA_REQUIRED` | 400 | `POST /transcriptions` |
| `MEDIA_TOO_LONG` | 400 | `POST /transcriptions` |
| `MISSING_WORKSPACE_ID` | 400 | any route |
| `MODE_UNSUPPORTED` | 400 | `POST /generations` |
| `MODEL_UNAVAILABLE` | 400 | `POST /generations`, `POST /generations/improve` |
| `NO_PENDING_ITEMS` | 400 | `POST /posts/{id}/publish` |
| `NO_RENDERS_SELECTED` | 400 | `POST /renders/bulk-download` |
| `NOTHING_TO_UPDATE` | 400 | `PATCH /posts/{id}` |
| `PERMISSION_MISSING` | 400 | `DELETE /posts/{id}/items/{itemId}` |
| `PLATFORM_UNAVAILABLE` | 400 | `POST /posts` |
| `PRODUCT_URL_INVALID` | 400 | `POST /personas/{id}/shots/product` |
| `PUBLISHED_ID_MISSING` | 400 | `DELETE /posts/{id}/items/{itemId}` |
| `RATIO_INVALID` | 400 | `POST /generations` |
| `RESOLUTION_INVALID` | 400 | `POST /generations` |
| `SCENE_ACTION_UNSUPPORTED` | 400 | `POST /personas/{id}/shots` |
| `SCHEDULE_LOCKED` | 400 | `PATCH /posts/{id}` |
| `SECONDS_INVALID` | 400 | `POST /generations` |
| `STYLE_REQUIRED` | 400 | `GET /personas/swap/quote`, `POST /personas/{id}/videos` |
| `STYLE_UNSUPPORTED` | 400 | `GET /personas/swap/quote`, `POST /personas/{id}/videos` |
| `TARGET_UNSUPPORTED` | 400 | `POST /personas/{id}/videos` |
| `TIMEFRAME_OUT_OF_BOUNDS` | 400 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `TIMEFRAME_TOO_SHORT` | 400 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `TOO_MANY_RENDERS` | 400 | `POST /renders/bulk-download` |
| `VALIDATION_ERROR` | 400 | any route |
| `VIDEO_DURATION_OUT_OF_RANGE` | 400 | `GET /personas/swap/quote`, `POST /personas/{id}/videos` |
| `VIDEO_TOO_LONG` | 400 | `POST /videos/upload/complete`, `POST /clips`, `POST /clips/info`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `VIDEO_TOO_SHORT` | 400 | `POST /videos/upload/complete` |
| `VIDEO_UNSUPPORTED` | 400 | `GET /personas/swap/quote`, `POST /personas/{id}/videos` |
| `VOICE_INVALID` | 400 | `POST /generations` |
| `WORKSPACE_NOT_AUTHORIZED` | 400 | any route |
| `UNAUTHORIZED` | 401 | any route |
| `CREDIT_CHARGE_FAILED` | 402 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `INSUFFICIENT_CREDITS` | 402 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry`, `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop`, `POST /transcriptions`, `POST /personas`, `POST /personas/{id}/regenerate`, `POST /personas/{id}/videos`, `POST /personas/{id}/shots`, `POST /generations`, `POST /generations/improve` |
| `ACCESS_DENIED` | 403 | `POST /clips/info` |
| `ACCOUNT_BLOCKED` | 403 | any route |
| `AGE_RESTRICTED` | 403 | `POST /clips/info` |
| `CLIP_FORBIDDEN` | 403 | `DELETE /clips/{videoId}` |
| `CLIP_RESULT_FORBIDDEN` | 403 | `DELETE /clips/{videoId}/submissions/{submissionId}/clips/{clipId}` |
| `COPYRIGHT_BLOCKED` | 403 | `POST /clips/info` |
| `DAILY_LIMIT_EXCEEDED` | 403 | `POST /posts` |
| `FORBIDDEN` | 403 | any route |
| `LIVE_CLIPS_NOT_AVAILABLE` | 403 | `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop` |
| `PLATFORM_NOT_SUPPORTED` | 403 | `POST /clips`, `POST /clips/info`, `POST /clips/{videoId}/submissions/{submissionId}/retry`, `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop` |
| `POST_FORBIDDEN` | 403 | `DELETE /posts/{id}/items/{itemId}` |
| `PRIVATE_VIDEO` | 403 | `POST /clips/info` |
| `REGION_BLOCKED` | 403 | `POST /clips/info` |
| `RENDER_FORBIDDEN` | 403 | `DELETE /renders/{renderId}` |
| `SUBMISSION_FORBIDDEN` | 403 | `DELETE /clips/{videoId}/submissions/{submissionId}` |
| `WORKSPACE_FORBIDDEN` | 403 | any route |
| `CLIP_NOT_FOUND` | 404 | `DELETE /clips/{videoId}`, `GET /clips/{videoId}/submissions`, `DELETE /clips/{videoId}/submissions/{submissionId}`, `DELETE /clips/{videoId}/submissions/{submissionId}/clips/{clipId}`, `GET /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/subtitles`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render` |
| `CLIP_RESULT_NOT_FOUND` | 404 | `DELETE /clips/{videoId}/submissions/{submissionId}/clips/{clipId}`, `GET /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/subtitles`, `POST /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/render` |
| `CONNECTION_NOT_FOUND` | 404, 400 | `GET /connections/{id}`, `DELETE /posts/{id}/items/{itemId}` |
| `CREATOR_NOT_FOUND` | 404 | `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop` |
| `EDIT_NOT_FOUND` | 404 | `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render`, `POST /renders` |
| `EDITS_NOT_FOUND` | 404 | `POST /posts`, `PATCH /posts/{id}` |
| `FACE_NOT_FOUND` | 404 | `POST /personas` |
| `FILE_NOT_FOUND` | 404 | `POST /videos/upload/multipart/complete`, `POST /videos/upload/multipart/abort`, `POST /videos/upload/complete`, `POST /personas/sources/upload/complete` |
| `GENERATION_NOT_FOUND` | 404 | `GET /generations/{id}`, `DELETE /generations/{id}`, `POST /generations/{id}/edit`, `POST /generations/{id}/feedback`, `POST /generations/{id}/refund`, `GET /generations/{id}/download` |
| `IMAGE_NOT_FOUND` | 404 | `POST /generations` |
| `ITEM_NOT_FOUND` | 404 | `POST /posts/{id}/items/{itemId}/retry`, `DELETE /posts/{id}/items/{itemId}` |
| `JOB_NOT_FOUND` | 404 | `GET /renders/bulk-download/{jobId}` |
| `MEDIA_NOT_FOUND` | 404 | `POST /transcriptions`, `GET /personas/swap/quote`, `POST /personas/{id}/videos` |
| `METADATA_UNAVAILABLE` | 404 | `POST /clips/info` |
| `MONITORING_NOT_FOUND` | 404 | `POST /monitors`, `GET /monitors/{id}`, `PATCH /monitors/{id}`, `DELETE /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop`, `GET /monitors/{id}/broadcasts`, `GET /monitors/{id}/broadcasts/{broadcastId}/clips`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/apply_template`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render` |
| `NO_SUBTITLES` | 404 | `GET /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/subtitles` |
| `NO_VALID_RENDERS` | 404 | `POST /renders/bulk-download` |
| `NO_VIDEO_INFO` | 404 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `NOT_FOUND` | 404 | any route |
| `PERSONA_NOT_FOUND` | 404 | `POST /personas/presets/{presetId}`, `POST /personas`, `GET /personas/{id}`, `DELETE /personas/{id}`, `POST /personas/{id}/regenerate`, `POST /personas/{id}/versions/{versionId}/restore`, `POST /personas/{id}/versions/{versionId}/feedback`, `POST /personas/{id}/save`, `POST /personas/{id}/videos`, `POST /personas/{id}/shots/product`, `POST /personas/{id}/shots` |
| `PHOTO_NOT_FOUND` | 404 | `POST /personas/{id}/shots` |
| `POST_NOT_FOUND` | 404 | `GET /posts/{id}`, `PATCH /posts/{id}`, `POST /posts/{id}/publish`, `POST /posts/{id}/items/{itemId}/retry`, `DELETE /posts/{id}/items/{itemId}` |
| `PRESET_NOT_FOUND` | 404 | `POST /personas/presets/{presetId}`, `PUT /personas/presets/{presetId}/favorite` |
| `RENDER_NOT_FOUND` | 404 | `GET /renders/{renderId}`, `DELETE /renders/{renderId}`, `GET /renders/{renderId}/download` |
| `SHOT_NOT_FOUND` | 404 | `GET /personas/{id}/shots/{shotId}` |
| `STRATEGY_NOT_FOUND` | 404 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry`, `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop` |
| `STREAM_NOT_FOUND` | 404 | `GET /monitors/{id}/broadcasts/{broadcastId}/clips` |
| `SUBMISSION_NOT_FOUND` | 404 | `GET /clips/{videoId}/submissions/{submissionId}`, `DELETE /clips/{videoId}/submissions/{submissionId}`, `POST /clips/{videoId}/submissions/{submissionId}/retry`, `POST /clips/{videoId}/submissions/{submissionId}/apply_template`, `GET /clips/{videoId}/submissions/{submissionId}/clips`, `DELETE /clips/{videoId}/submissions/{submissionId}/clips/{clipId}`, `GET /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/subtitles` |
| `TEMPLATE_NOT_FOUND` | 404 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry`, `POST /clips/{videoId}/submissions/{submissionId}/apply_template`, `POST /monitors`, `PATCH /monitors/{id}`, `POST /monitors/{id}/start`, `POST /monitors/{id}/stop`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/apply_template` |
| `TRANSCRIPTION_NOT_FOUND` | 404 | `GET /transcriptions/{transcriptionId}`, `DELETE /transcriptions/{transcriptionId}`, `GET /transcriptions/{transcriptionId}/transcript`, `GET /transcriptions/{transcriptionId}/download` |
| `UNAVAILABLE` | 404 | `POST /clips/info` |
| `VERSION_NOT_FOUND` | 404 | `POST /personas/{id}/versions/{versionId}/restore`, `POST /personas/{id}/versions/{versionId}/feedback`, `POST /personas/{id}/videos`, `POST /personas/{id}/shots` |
| `VIDEO_ID_NOT_FOUND` | 404 | `POST /clips/info` |
| `VIDEO_NOT_FOUND` | 404 | `GET /clips/{videoId}/submissions/{submissionId}`, `POST /personas/{id}/videos/{videoId}/feedback`, `GET /personas/{id}/videos/{videoId}` |
| `WORKSPACE_NOT_FOUND` | 404 | `GET /workspace` |
| `STORAGE_LIMIT_EXCEEDED` | 406 | `POST /transcriptions/upload`, `POST /personas/sources/upload`, `POST /generations/images` |
| `CARD_LOCKED` | 409 | `POST /personas/{id}/regenerate`, `POST /personas/{id}/versions/{versionId}/restore` |
| `CARD_NOT_READY` | 409 | `POST /personas/{id}/save` |
| `DUPLICATE_POST` | 409 | `POST /posts` |
| `MEDIA_REFUNDED` | 409 | `POST /posts`, `PATCH /posts/{id}` |
| `PRICE_CHANGED` | 409 | `POST /personas/{id}/videos`, `POST /personas/{id}/shots`, `POST /generations` |
| `REFUND_AFTER_DOWNLOAD` | 409 | `POST /generations/{id}/refund` |
| `REFUND_AFTER_POST` | 409 | `POST /generations/{id}/refund` |
| `REFUND_ALREADY_REQUESTED` | 409 | `POST /generations/{id}/refund` |
| `REFUND_NOT_ALLOWED` | 409 | `POST /generations/{id}/refund` |
| `RENDER_ALREADY_IN_PROGRESS` | 409 | `POST /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/render`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render`, `POST /renders` |
| `SUBMISSION_NOT_FAILED` | 409 | `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `TRANSCRIPTION_NOT_READY` | 409 | `GET /transcriptions/{transcriptionId}/transcript`, `GET /transcriptions/{transcriptionId}/download` |
| `VIDEO_ALREADY_PROCESSING` | 409 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `VIDEO_IN_PROGRESS` | 409 | `POST /personas/{id}/videos` |
| `JOB_EXPIRED` | 410 | `GET /renders/bulk-download/{jobId}` |
| `RECORDING_EXPIRED` | 410 | `GET /monitors/{id}/broadcasts/{broadcastId}/clips`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render`, `POST /posts` |
| `RENDER_FILE_EXPIRED` | 410 | `GET /renders/{renderId}/download` |
| `SUBMISSION_EXPIRED` | 410 | `GET /clips/{videoId}/submissions/{submissionId}`, `GET /clips/{videoId}/submissions/{submissionId}/clips` |
| `AUDIO_ONLY` | 422 | `POST /clips/info` |
| `CHANNEL_URL` | 422 | `POST /clips/info` |
| `INVALID_DIMENSIONS` | 422 | `POST /clips/info` |
| `INVALID_DURATION` | 422 | `POST /clips/info` |
| `INVALID_URL` | 422 | `POST /clips/info` |
| `LIVE_STREAM` | 422 | `POST /clips/info` |
| `MEDIA_UNREADABLE` | 422 | `POST /transcriptions`, `POST /personas/sources/upload/complete` |
| `PLAYLIST_URL` | 422 | `POST /clips/info` |
| `PREMIUM_ONLY` | 422 | `POST /clips/info` |
| `PRODUCT_NOT_READABLE` | 422 | `POST /personas/{id}/shots/product` |
| `SHORTS_NOT_SUPPORTED` | 422 | `POST /clips/info` |
| `BATCH_ALREADY_RUNNING` | 429 | `POST /clips/{videoId}/submissions/{submissionId}/apply_template`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/apply_template` |
| `PRODUCT_RATE_LIMITED` | 429 | `POST /personas/{id}/shots/product` |
| `RATE_LIMIT_EXCEEDED` | 429 | `POST /clips/info`, `POST /monitors` |
| `TOO_MANY_PENDING_CLIPS` | 429 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `TOO_MANY_RUNNING` | 429 | `POST /generations` |
| `CANCEL_FAILED` | 500 | `DELETE /renders/{renderId}` |
| `CREDIT_CHARGE_ERROR` | 500 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `FAILED_TO_GET_VIDEO` | 500 | `POST /clips/info` |
| `INTERNAL_ERROR` | 500 | `POST /videos/upload/complete`, `POST /personas/sources/upload/complete` |
| `INTERNAL_SERVER_ERROR` | 500 | any route |
| `PRESIGN_FAILED` | 500 | `POST /videos/upload`, `POST /transcriptions/upload`, `POST /personas/sources/upload` |
| `PROCESSING_ERROR` | 500 | `POST /clips`, `POST /clips/{videoId}/submissions/{submissionId}/retry` |
| `RENDER_FAILED` | 500 | `POST /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/render`, `POST /monitors/{id}/broadcasts/{broadcastId}/clips/{clipId}/render`, `POST /renders` |
| `RENDER_SETUP_FAILED` | 500 | `POST /clips/{videoId}/submissions/{submissionId}/clips/{clipId}/render` |
| `SIGNED_URL_FAILED` | 500 | `GET /renders/{renderId}/download` |
| `UNKNOWN_ERROR` | 500 | `POST /clips/info`, `POST /posts` |
| `AI_UNAVAILABLE` | 502 | `POST /generations/improve` |
| `MEDIA_UNAVAILABLE` | 502 | `GET /personas/catalog`, `POST /personas/presets/{presetId}`, `GET /personas/swap/quote`, `POST /personas/{id}/videos`, `POST /personas/{id}/shots`, `POST /generations` |
| `SERVICE_UNAVAILABLE` | 503 | `POST /clips/info` |
