<!-- Source: https://docs.geopera.com/api-reference/errors · Markdown for LLMs -->

# Errors

Every error response uses the [RFC 7807](https://www.rfc-editor.org/rfc/rfc7807)
`application/problem+json` shape, so error handling is uniform across the whole API:

```json
{
  "type": "about:blank",
  "title": "Forbidden",
  "status": 403,
  "detail": "missing scope 'orders:write' for 'orders.archive.place'"
}
```

| Field | Meaning |
|---|---|
| `status` | The HTTP status code (mirrors the response status) |
| `title` | A short, stable human-readable summary of the error class |
| `detail` | A specific, contextual message about *this* error |
| `type` | A URI identifying the problem type (`about:blank` when the status is sufficient) |

The error model is owned by the kernel, so every operation returns errors the same way
— there is no per-endpoint error format to special-case.

## Status codes

| Code | Meaning | Typical cause |
|---|---|---|
| `400 Bad Request` | Malformed request | A structurally invalid body |
| `401 Unauthenticated` | No / invalid token | Missing or expired Bearer token |
| `403 Forbidden` | Insufficient scope or access | The principal lacks the operation's scope, or isn't a member of the target's project/org |
| `404 Not Found` | Unknown resource or operation | A bad id, or a resource outside your organization (returned as 404, not 403, to avoid leaking existence) |
| `402 Payment Required` | Cannot charge | Insufficient credits, no/declined card, or a past-due account |
| `409 Conflict` | State conflict | An invalid state transition, or a concurrent change that lost the race |
| `410 Gone` | Expired / retired | An expired approval or a retention-expired asset |
| `422 Unprocessable Entity` | Input failed validation | The body parsed but failed the operation's typed schema or a domain rule (e.g. invalid geometry) |
| `429 Too Many Requests` | Rate limited | Per-key rate limit or an egress/bandwidth limit |
| `500 Internal Server Error` | Server fault | An unexpected backend error |

## Validation errors

Because every operation has a typed input model, malformed inputs fail fast with
`422 Unprocessable Entity` *before* any side-effect runs — the wrong input never
reaches the handler. The `detail` field describes which field failed and why.

## Payment & spend errors

Spend operations (placing an order, topping up, creating a processing job) surface
billing problems as `402 Payment Required`:

- **Insufficient credits** — top up, or enable auto top-up.
- **No / declined card** — attach a payment method.
- **3-D Secure required** — the response carries a `client_secret` so the client can
  complete the bank challenge, then retry.

## Idempotent retries

Spend operations accept an `Idempotency-Key` header. If a request times out, retry it
with the **same key**: a duplicate is detected and the original result is returned
rather than charging or acting twice. This makes spend operations safe to retry on
network failure.

## A note on 403 vs 404

To avoid leaking the existence of resources across organizations, the platform returns
`404 Not Found` (not `403 Forbidden`) when you reference a resource that exists but
belongs to another organization. A `403` means *you authenticated, but your scope or
project membership doesn't permit this action on a resource you can see*.
