# Errors

An error is a decision, not a fault. A spent balance, a bad request and a missing key are three different answers with three different next steps, and they never share a message.

## The shape

Every error is JSON with one `error` object. `code` is stable and meant for your code to branch on; `message` is for a person. A `422` adds `details`: one entry per field, in wire spelling.

**422**

```
{
  "error": {
    "code": "invalid_request",
    "message": "The request does not fit this op. See error.details for the fields.",
    "details": [
      { "field": "request.sort", "message": "Input should be 'hot', 'newest', 'top' or 'rising'" }
    ]
  }
}
```

## Codes

| Status | Code | Means | Next step |
| --- | --- | --- | --- |
| 401 | `unauthorized` | No key, or one that is unknown, revoked or expired. | Create or rotate a key in the dashboard. |
| 402 | `insufficient_credits` | The balance cannot cover the call. | Top up, lower limit, or set maxCredits and accept named omissions. |
| 404 | `not_found` | No platform by that name. | GET /platforms lists what is served. |
| 422 | `invalid_request` | The body does not fit the op's schema. | error.details names each field and what was wrong with it. |
| 429 | `quota_exceeded` | A rate or allowance limit was hit. | Wait and retry; the limit is per period, not per balance. |
| 502 | `upstream_failed` | The call could not be completed right now. | Retry later. Nothing was charged. |
| 503 | `unavailable` | The service is temporarily unavailable. | Retry shortly. |

## What is not an error

A subject that could not be served is **not** an error. The call succeeds, the rest of the answer is whole, and the miss is named in `coverage.omitted` with a typed reason. Treating a partial answer as a failure invites retries that spend twice; read the omission instead.

---

Source: https://zomler.com/docs/api/errors
