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

# Errors

> Every endpoint returns the same error envelope with a stable, machine-readable code.

Every error, on every endpoint, uses the same envelope:

```json theme={null}
{
  "error": "invalid_request",
  "message": "2 members are missing fields required for enrollment.",
  "details": [
    { "index": 3, "field": "email", "message": "email is required for enrollment" },
    { "index": 9, "field": "lastName", "message": "lastName is required for enrollment" }
  ]
}
```

* **`error`**: a stable, machine-readable code. Branch on this.
* **`message`**: human-readable; wording may change, so never parse it.
* **`details`**: present on `invalid_request`, with one entry per failing field and an `index` when the payload is an array (census rows, enrollment member checks).

## Error codes

| Status | Code                 | Meaning                                                                                                              | What to do                                                                               |
| ------ | -------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| 400    | `invalid_request`    | Validation failed; see `details`.                                                                                    | Fix the listed fields and retry.                                                         |
| 401    | `unauthorized`       | Missing, malformed, or revoked API key.                                                                              | Check the `Authorization: Bearer` header and the key's status.                           |
| 403    | `live_mode_disabled` | Live key used before live mode is enabled for your account.                                                          | Stay on `psk_test_` until the [go-live checklist](/resources/compliance) is complete.    |
| 403    | `forbidden`          | The key may not access this resource.                                                                                | Verify you're using the right partner's key.                                             |
| 404    | `not_found`          | No such resource **in this mode**: test keys can't see live resources, and `account`/`members` 404 until enrollment. | Check the ID, the key's mode, and the group's lifecycle stage.                           |
| 409    | `conflict`           | Duplicate state: an enrolled group already exists for this domain, or the group already has an active enrollment.    | Treat as "already done"; fetch the existing resource and reconcile.                      |
| 410    | `quote_expired`      | The quote has passed its `expiresAt` (rate-card driven; default 30 days).                                            | Create a new quote (deterministic; an unchanged census re-prices identically) and retry. |
| 422    | `census_required`    | Quote requested with no quotable census.                                                                             | `PUT /census` first; each member needs `zip` + `dob` \| `age`.                           |
| 429    | `rate_limited`       | Rate limit exceeded. `Retry-After` header included.                                                                  | Back off per [Rate limits](/resources/rate-limits).                                      |
| 500    | `server_error`       | Failure on our side. The request was not applied.                                                                    | Retry with the same `Idempotency-Key`.                                                   |
| 503    | `not_configured`     | The API's backing store is unavailable; we fail closed rather than partially.                                        | Retry with backoff; contact your partner engineer if it persists.                        |

## Handling patterns that hold up

* **Branch on `error`, log `message`.** Codes are contractual; messages aren't.
* **`409` is usually success.** Both conflict cases mean "the thing you wanted already exists"; fetch it and continue rather than surfacing an error.
* **Retry `500`/`503` with the same `Idempotency-Key`** on POST/PUT. Replays within 24 hours are safe by construction; see [Rate limits & idempotency](/resources/rate-limits).
* **Don't blanket-retry `4xx`.** Other than `429` and the `410` re-quote flow, 4xx errors need a changed request, not a repeated one.
