> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.emtelligent.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.emtelligent.com/_mcp/server.

# Errors

## Error responses

Every error response has the same shape:

```json
{
  "error": {
    "code": "invalid_credentials",
    "message": "invalid credentials",
    "request_id": "req_3b1f0c9e8d7a6b5c4d3e"
  }
}
```

Branch on `code`, which is stable. `message` is for people and may change. The `request_id`
is also returned in the `X-Request-Id` header; quote it when contacting support.

| HTTP | `code`                                   | Meaning and what to do                                                                                        |
| ---- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| 400  | `invalid_idempotency_key`                | The `Idempotency-Key` header is not 1 to 128 of `A-Z a-z 0-9 _ . : -`                                         |
| 401  | `invalid_credentials`                    | The key is missing, unknown, expired or revoked, or lacks the `synth:process` scope                           |
| 402  | `organization_suspended`                 | The organization is suspended. See [Billing](/platform/billing)                                               |
| 402  | `insufficient_credit`                    | Not enough credit for the most this request can produce. Nothing was queued. See [Billing](/platform/billing) |
| 404  | `not_found`                              | No such job or cohort for your organization, or a result that wasn't requested                                |
| 409  | `idempotency_conflict`                   | That `Idempotency-Key` was already used with a different body                                                 |
| 409  | `not_ready`                              | A result was requested before the job finished                                                                |
| 409  | `no_result`                              | The job failed or was canceled, so it has no results                                                          |
| 410  | `result_expired`                         | The result was already downloaded, or was not downloaded within 24 hours                                      |
| 422  | `request_validation`                     | A field has the wrong type or value, or is not recognised. The message names the fields                       |
| 422  | `too_many_documents`, `cohort_too_large` | Over a [limit](/synth/reference/limits)                                                                       |
| 429  | `rate_limited`                           | Over a rate or concurrency [limit](/synth/reference/limits). Wait for the `Retry-After` seconds               |
| 500  | `internal_error`                         | A problem on our side. Retry, and contact support if it persists                                              |
| 503  | `temporarily_unavailable`                | Retry with backoff                                                                                            |

## Failed jobs

A job or cohort can fail after it was accepted. Its status is then `failed`, with an error:

```json
{ "id": "…", "status": "failed",
  "error": { "code": "generation_failed",
             "message": "this patient could not be generated; resubmit, or contact support if it persists" }, … }
```

| `error.code`              | Meaning and what to do                                                                                                                       |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_request`         | The request cannot be generated as asked, for example a birth date after the start of the timeline. The message says why. Change the request |
| `generation_failed`       | The patient (or the cohort's health system) could not be generated. Resubmit; if it keeps failing, contact support with the job `id`         |
| `temporarily_unavailable` | Generation was interrupted on our side. Resubmit                                                                                             |
| `processing_interrupted`  | Processing was interrupted on our side. Resubmit                                                                                             |
| `all_patients_failed`     | Every patient in a cohort failed. Each patient's error is in the cohort's `result`                                                           |

A job we cancel ourselves, for operational reasons, has status `canceled` and the code
`canceled_by_operator`. Resubmit it.

A cohort in which some patients failed still succeeds: those patients are listed in
`summary.failures`, each with its error, and are not billed.

New codes may be added. Treat an unrecognised code as a problem on our side.

## Retrying safely

Send an `Idempotency-Key` header, of your choosing, with every submission:

```
Idempotency-Key: order-1234
```

Resubmitting with the same key and the same body returns the original job or cohort, with
`200` rather than `202`, instead of creating, and charging for, a second one. The same key
with a different body is rejected with `409 idempotency_conflict`. Keys are scoped to your
organization and remembered for 24 hours.

Retry `429` responses after the `Retry-After` seconds. Retry `503` and `500` responses, and
network errors, with exponential backoff. Do not retry other `4xx` responses unchanged: they
will fail the same way.