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

# Errors & limits

> Status codes, error shape, and rate limits.

## Error shape

Every error uses a standard HTTP status code and a consistent JSON envelope:

```json theme={null}
{ "error": { "code": "report_not_ready", "message": "Report is not available yet for this review." } }
```

Branch your integration on the stable `error.code` (a closed, documented set),
not on the HTTP status alone (several distinct conditions can share a status)
and never on the human-readable `error.message` (it is advisory and may change).

## Error codes

| `code`                         | HTTP status   | Meaning                                                                                                                                         |
| ------------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `missing_api_key`              | `401`         | No API key was sent. Add `Authorization: Bearer <key>`.                                                                                         |
| `invalid_api_key`              | `401`         | The API key is invalid, revoked, or expired.                                                                                                    |
| `org_unbound`                  | `403`         | The key is valid but not bound to an organization.                                                                                              |
| `auth_unavailable`             | `503`         | Authentication is temporarily unavailable; retry shortly.                                                                                       |
| `review_not_found`             | `404`         | The review does not exist or belongs to another organization.                                                                                   |
| `report_not_ready`             | `404`         | The review exists but has not finished; keep polling.                                                                                           |
| `report_not_ready`             | `409`         | The review's release exists but its report render is unavailable; Flightline will not substitute a different one. Contact support.              |
| `review_failed`                | `422`         | The review failed (terminal); no report will exist.                                                                                             |
| `document_required`            | `400`         | No usable document was supplied (or a file was empty).                                                                                          |
| `document_unsupported`         | `400`         | A document, archive, or archive member has an unsupported type.                                                                                 |
| `document_too_large`           | `413`         | A single document exceeds the per-file size limit.                                                                                              |
| `too_many_documents`           | `422`         | More documents than the per-review limit.                                                                                                       |
| `documents_too_large`          | `422`         | The documents exceed the aggregate per-review size limit.                                                                                       |
| `duplicate_reference_id`       | `409`         | A review with the same `reference_id` already exists.                                                                                           |
| `all_documents_duplicate`      | `409`         | Every submitted document duplicates one already on the review.                                                                                  |
| `working_doc_flattened`        | `422`         | A Flightline working doc whose fillable fields are gone (flattened, printed, or scanned). Re-upload the original PDF filled without flattening. |
| `working_doc_not_review_input` | `422`         | A Flightline working doc was submitted to create a new review. A working doc is a response to an existing review, not an input for a new one.   |
| `invalid_request`              | `400` / `422` | The request body or a field is malformed (bad JSON, failed validation, unfetchable source URL).                                                 |
| `rate_limited`                 | `429`         | Rate limit exceeded; retry with exponential backoff.                                                                                            |
| `webhook_endpoint_not_found`   | `404`         | The webhook endpoint does not exist under your organization.                                                                                    |
| `internal_error`               | `500`         | An unexpected server error; retry later.                                                                                                        |

## Review lifecycle & the failure contract

A review's `status` moves through `queued` → `processing` → **`completed`** or **`failed`**. Both `completed` and `failed` are terminal; stop polling once you see either.

`GET /reviews/{review_id}/report` uses the status code to tell you what to do, so a failure is never mistaken for "still processing":

| Report status | Meaning                                                                    | What to do                                                                                      |
| ------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `200`         | Review `completed`; report body follows.                                   | Use the report.                                                                                 |
| `404`         | Review not found, or not finished yet (`queued`/`processing`).             | Keep polling.                                                                                   |
| `409`         | Review `completed`, but the report render for this release is unavailable. | Stop polling this endpoint; contact support. Flightline will not substitute a different render. |
| `422`         | Review `failed` (terminal). No report will ever exist.                     | Stop polling; inspect the review and resubmit if appropriate.                                   |

Always confirm terminal state via `GET /reviews/{review_id}` (`status` is `completed` or `failed`) rather than inferring it from the report endpoint alone.

## Rate limits

Requests are rate-limited **per organization** (the default ceiling is 60
requests/minute, enforced across our fleet). Exceeding it returns `429 Too
Many Requests`.

### Response headers

Every rate-limited response carries the standard rate-limit headers so you can
observe your remaining budget without waiting for a `429`:

| Header                  | Meaning                                           |
| ----------------------- | ------------------------------------------------- |
| `X-RateLimit-Limit`     | Your ceiling for the current window.              |
| `X-RateLimit-Remaining` | Requests left in the current window.              |
| `X-RateLimit-Reset`     | Unix timestamp (seconds) when the window resets.  |
| `Retry-After`           | Seconds to wait before retrying. Sent on a `429`. |

On a `429`, **honor `Retry-After`** if present; otherwise **retry with
exponential backoff** (e.g. 1s, 2s, 4s, … with jitter) rather than
tight-looping. Watching `X-RateLimit-Remaining` lets you pace requests and
avoid a `429` entirely. Webhooks let you avoid polling altogether and stay well
under any limit. If your integration needs a higher ceiling, contact your
Flightline representative.

## Idempotency

Set `reference_id` to your own external identifier for the loan package.
Creating a second review with a `reference_id` that already exists returns
`409`, so retries won't create duplicate reviews.
