> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reedapt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Every error has the same shape, an HTTP status, and a stable code to branch on.

When a request fails, the answer has a `4xx` or `5xx` status and this body:

```json theme={null}
{
  "error": {
    "code": "UPLOAD_INCOMPLETE",
    "message": "Complete the upload before dubbing it.",
    "request_id": "req_8f2c1e0a9b7d6c5e4f3a"
  }
}
```

* **`code`** stays the same over time. Write your logic against it.
* **`message`** explains the problem in plain English. You can show it to people, but its wording may change.
* **`request_id`** identifies the request. Quote it when you contact us. Every answer, successful or not, also carries it in the `Request-Id` header.

When fields are missing or invalid, `code` is `INVALID_REQUEST` and `fields` lists each problem:

```json theme={null}
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Some fields are missing or invalid.",
    "request_id": "req_…",
    "fields": [{ "field": "target_languages", "message": "Field required" }]
  }
}
```

We may add codes. Treat a code you don't recognise by its HTTP status.

## Statuses

| Status | Meaning | What to do |
| - | - | - |
| `401` | The key is missing, wrong or revoked. | Check the key. Don't retry. |
| `404` | Nothing with this id belongs to your account. | Check the id. |
| `409` | The request conflicts with the object's state. | Read the code. Usually wait, or start over. |
| `413` | The request body is over 256 KiB. | Send files through uploads, not in the request. |
| `422` | The request can't be done as asked. | Fix the request. Don't retry it unchanged. |
| `429` | Too many requests, or a limit was reached. | Wait for `Retry-After` seconds. |
| `500` | Something went wrong on our side. | Retry with backoff. |
| `503` | Something is briefly unavailable. | Retry after `Retry-After` seconds. |

## Codes

### Keys and limits

| Code | Status | Meaning |
| - | - | - |
| `UNAUTHORIZED` | 401 | The key is missing, wrong or revoked. |
| `RATE_LIMITED` | 429 | Too many requests. See [Rate limits](https://docs.reedapt.com/rate-limits.md). |
| `UNAVAILABLE` | 503 | We can't check keys right now. Retry in a minute. |
| `INTERNAL` | 500 | Something went wrong on our side. |
| `BODY_TOO_LARGE` | 413 | Request bodies can be at most 256 KiB. |
| `LENGTH_REQUIRED` | 411 | Send a `Content-Length` with the body. |
| `INVALID_REQUEST` | 422 | Missing or invalid fields; see `fields`. |

### Uploads

| Code | Status | Meaning |
| - | - | - |
| `UNSUPPORTED_FILE_TYPE` | 422 | We don't dub this kind of file, or can't tell its type from the link. |
| `FILE_TOO_LARGE` | 422 | The file is bigger than your plan allows. |
| `UPLOAD_COMPLETE` | 409 | The upload is already complete. |
| `UPLOAD_FETCHING` | 409 | We're downloading this file from its link; there's nothing to complete. |
| `UPLOAD_PARTS_MISMATCH` | 409 | Some parts are missing or their ETags don't match. |
| `UPLOAD_GONE` | 404 | The upload expired, or the file didn't match the declared size. Start again. |
| `SOURCE_URL_INVALID` | 422 | The link isn't a usable `http(s)` address. |
| `SOURCE_URL_NOT_PUBLIC` | 422 | The link doesn't lead to a public address. |
| `SOURCE_URL_REDIRECTS` | 422 | The link redirects too many times. |
| `TOO_MANY_FETCHES` | 429 | Three links are already downloading for your account. |
| `FETCHES_BUSY` | 503 | We're downloading many links right now. Retry later. |

A download from a link that fails after the upload was created sets the upload to `failed`, with one of these as its `error`: the link answered with an error, sent an empty file, was too slow, or the file was bigger than your plan allows.

### Dubs

| Code | Status | Meaning |
| - | - | - |
| `UPLOAD_INCOMPLETE` | 409 | The upload isn't complete, or is still downloading. |
| `UPLOAD_FAILED` | 409 | The upload failed. Upload the file again. |
| `UPLOAD_USED` | 409 | The upload was already dubbed. Upload the file again to dub it again. |
| `NOT_ENOUGH_MINUTES` | 422 | Not enough minutes left for this file. |
| `LANGUAGE_NOT_IN_PLAN` | 422 | Your plan doesn't include this language. |
| `LANGUAGE_PAUSED` | 422 | Dubbing into this language is paused for now. |
| `BULK_NOT_ON_PLAN` | 422 | Several languages in one request needs a plan with bulk dubbing. |
| `TOO_MANY_DUBS_RUNNING` | 429 | Your plan's limit of unfinished dubs is reached. Start more once some finish. |
| `TEST_KEY_VIDEO_ONLY` | 422 | Test keys dub video files. Use a live key for audio. |
| `TEST_DUB_LIMIT` | 429 | The test key's dubs for today are used up. |
| `TEST_DUBS_UNAVAILABLE` | 503 | Test dubs can't start right now. Retry later. |
| `USAGE_UNAVAILABLE` | 503 | We couldn't check your minutes. Retry shortly. |
| `DUB_COMPLETE` | 409 | The dub is finished, so it can't be cancelled. |
| `DUB_NOT_READY` | 409 | The dub isn't finished, so it has no files yet. |
| `FILES_GONE` | 404 | The dub's files are no longer stored. |

### Repeated requests

| Code | Status | Meaning |
| - | - | - |
| `IDEMPOTENCY_MISMATCH` | 422 | This `Idempotency-Key` was used for a different request. |
| `IDEMPOTENCY_IN_PROGRESS` | 409 | A request with this key is still running. Retry shortly. |
| `ALREADY_STARTED` | 409 | The first request was cut off after its dubs started. Find them with `GET /dubs`. |

### Webhooks

| Code | Status | Meaning |
| - | - | - |
| `WEBHOOK_URL_INVALID` | 422 | The URL must be a valid `https://` address. |
| `WEBHOOK_URL_NOT_PUBLIC` | 422 | The URL doesn't lead to a public address. |
| `WEBHOOK_LIMIT` | 422 | The account has as many endpoints as it can. Delete one first. |

## Why a dub failed

A dub that fails after it started has `status: "failed"` and an `error` with one of these codes. Its minutes are returned.

| Code | Meaning |
| - | - |
| `NO_AUDIO_TRACK` | The file has no sound to dub. |
| `NO_SPEECH` | We couldn't find any speech in the file. |
| `UNREADABLE_MEDIA` | The file is damaged or in a format we can't read. |
| `TRANSCRIPTION_FAILED` | We couldn't transcribe the audio clearly. |
| `TRANSLATION_FAILED`, `TRANSLATION_UNAVAILABLE` | Translation didn't work this time. Try again. |
| `TTS_ALL_SEGMENTS_FAILED` | We couldn't make the voices for this language right now. |
| `AUDIO_SEPARATION_FAILED` | We couldn't process the audio in this file. |
| `PROCESSING_TIMEOUT`, `RESOURCE_OOM` | The file was too long or heavy to process right now. |
| `RECOVERY_LIMIT_REACHED` | The dub stopped more than once before finishing. |
| `CANCELLED` | You cancelled it. |
| `DUB_FAILED` and other codes | Something went wrong on our side. Try again, and contact us with the dub's id if it keeps happening. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.