# Errors

> The single error shape, every code the API returns, and which ones are worth retrying.

Source: https://www.propexecutor.com/docs/errors
Whole reference in one file: https://www.propexecutor.com/doc.md

Every error has the same shape, whatever went wrong. Branch on `code`, which is stable; show or log `message`, which is written for a human and may be reworded.

<!-- Error response -->
```json
{
  "error": {
    "code": "account_not_found",
    "message": "no such trading account"
  }
}
```

## Codes

| Status | Code | Means | Retry? |
| --- | --- | --- | --- |
| `400` | `invalid_body` | The JSON did not parse, or a required field is missing. | No — fix the request. |
| `400` | `invalid_account_number` | The path segment is not an 8-digit account number. | No |
| `400` | `invalid_cursor` | The cursor was not one we issued. | No — restart paging. |
| `400` | `invalid_range` | `from` is not before `to`. | No |
| `401` | `invalid_api_key` | Unknown or revoked key. | No |
| `402` | `quota_exhausted` | Not enough account credits to provision what you asked for. | No — buy credits. |
| `403` | `missing_scope` | The key lacks the scope this endpoint needs. | No |
| `404` | `account_not_found` | No such account in your organization. | No |
| `409` | `idempotency_mismatch` | An `Idempotency-Key` was reused with a different body. | No |
| `429` | `rate_limited` | Over the per-key budget. | Yes — after `Retry-After`. |
| `503` | `busy` | The database pool is saturated. | Yes — shortly. |
| `503` | `curve_unavailable` | The equity curve is not configured on this deployment. | No |

> **Retry only 429 and 503**
> Those two are the only ones where the same request can succeed later. Everything else means the request itself needs changing, and retrying it just burns your rate limit. Use exponential backoff with jitter, and honour `Retry-After` when it is present.

## A 404 means “not yours” too

An account belonging to a different organization returns the same `404` as one that does not exist. Tenant isolation is enforced in the database, so there is no way to tell the two apart — and no way to probe for other firms’ accounts.
