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

# Errors

> Every HTTP status code the API returns, when it fires, and how to respond.

Errors are returned as JSON with a `detail` field. Status-code semantics
follow HTTP conventions — retry 5xx, don't retry 4xx (except 429).

## Status codes

| Code  | Name                 | When                                                                                                                                                       | How to respond                                              |
| ----- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `200` | OK                   | Successful inference                                                                                                                                       | Parse body                                                  |
| `401` | Unauthorized         | Missing, invalid, or revoked API key                                                                                                                       | Check your `Authorization` header — don't retry until fixed |
| `422` | Unprocessable Entity | Request body failed validation (e.g. both `resources` and `bundle` empty, or unknown `format`/`verbosity` value)                                           | Fix payload — don't retry                                   |
| `429` | Too Many Requests    | Rate limit or monthly cap exceeded                                                                                                                         | Respect `Retry-After`; back off                             |
| `503` | Service Unavailable  | Transient infra failure (rare — e.g. auth verification briefly unavailable during a deploy, or the OCR engine momentarily unreachable on the PDF endpoint) | Retry with backoff                                          |

## Shape

<ResponseExample>
  ```json Simple errors (most) theme={null}
  { "detail": "missing API key" }
  ```
</ResponseExample>

<ResponseExample>
  ```json Structured errors (rate/quota) theme={null}
  {
    "detail": {
      "error": "rate_limit_exceeded",
      "limit_per_minute": 60,
      "plan": "starter"
    }
  }
  ```
</ResponseExample>

<ResponseExample>
  ```json Validation errors (Pydantic / FastAPI) theme={null}
  {
    "detail": [
      {
        "type": "value_error",
        "loc": ["body"],
        "msg": "request must include `resources` and/or `bundle`",
        "input": {}
      }
    ]
  }
  ```
</ResponseExample>

## Common scenarios

<AccordionGroup>
  <Accordion title="401 — missing API key">
    You sent a request without an `Authorization: Bearer ...` header, or the
    key has been revoked. Generate a new one from the
    [portal](https://medlistiq.com/dashboard/keys).
  </Accordion>

  <Accordion title="422 — request must include `resources` and/or `bundle`">
    You sent `{ "resources": [] }` with nothing else. At least one of
    `resources` (non-empty array) or `bundle` (non-empty FHIR Bundle) must be
    present. See the [Quickstart](/quickstart) for a minimal working request.
  </Accordion>

  <Accordion title="429 — rate limit exceeded">
    You exceeded your plan's per-minute limit. Back off for the number of
    seconds in the `Retry-After` header, then retry. If you're hitting this
    often, consider upgrading to Starter or Pro.
  </Accordion>

  <Accordion title="429 — monthly cap reached">
    Your org has used all of its monthly request allowance. The `upgrade_url`
    in the response points to your billing page. Usage resets on the 1st of
    next month (UTC).
  </Accordion>

  <Accordion title="422 — file 'X' does not look like a PDF">
    Specific to `POST /v1/med-lists/from-documents`. We check that every
    upload starts with the `%PDF-` magic header before sending it downstream;
    a renamed `.txt`, `.docx`, or image triggers this. Rename and re-export
    as a real PDF, or drop the offending file from the request.
  </Accordion>

  <Accordion title="422 — too many files / payload exceeds page limit">
    Specific to `POST /v1/med-lists/from-documents`. The per-request limits are
    15 files, 50 MB per file, 150 MB total, and 200 pages combined after
    parsing. Split larger packets into multiple calls; server-side batching is
    on the roadmap. See [Med lists from PDFs](/from-documents) for the full
    list of validation messages.
  </Accordion>
</AccordionGroup>

## Retries

For retryable errors (5xx, 429), use exponential backoff. Starting point:

* 429: respect `Retry-After`
* 503: 1s, 2s, 4s, 8s, then give up

Don't retry 4xx other than 429 — they indicate the request itself is malformed
and won't succeed on retry.

## Getting a request ID

Every response includes an `x-request-id` response header. If you open a
support ticket, include that ID — we can trace the exact request in our logs.

For `/v1/medications/infer`, the same ID also appears inside the response
body as `meta.request_id`. The PDF endpoint returns body-only and surfaces
all metadata (request ID, page counts, processing time, ruleset version) via
response headers — see [Med lists from PDFs](/from-documents#response-shape).
