# Public API errors

Every error, from a refused token to a failed validation, answers with the same body: RFC 7807 problem details, sent as `application/problem+json`, with a machine-readable `code` and whether a retry can succeed.

```json
{
  "type": "about:blank",
  "title": "Validation Failed",
  "status": 400,
  "code": "validation_failed",
  "retryable": false,
  "traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
  "errors": [
    { "name": "amount", "reason": "\"1.123456789\" is not a decimal amount with at most 8 decimal places." }
  ]
}
```

## The fields

| Field | Meaning |
|---|---|
| `status` | The HTTP status, repeated in the body. |
| `code` | What went wrong, in snake case, such as `not_found` or `validation_failed`. It stays the same across releases; branch on it, never on the text. |
| `retryable` | Whether repeating the same request later can succeed. |
| `title`, `detail` | A summary and, when there is one, the specifics, for a person to read. The wording can change. |
| `traceId` | The request's trace. Quote it when you contact support. |
| `errors` | The individual failures: one entry per invalid field, with its `name` and `reason`, or one general entry. |

## Status codes

| Status | When |
|---|---|
| `400` | The request is malformed or a field is invalid; `errors` names each field. |
| `401` | The token is missing, invalid, expired or revoked. |
| `403` | The token lacks the operation's capability, or a workspace token names another workspace; see [Authentication](/api/authentication). |
| `404` | The object does not exist or is not visible to this token. |
| `409` | The request conflicts with the object's current state, or with a change made at the same moment. A deletion refused because something still uses the object, such as a budget measuring a cost report, answers `in_use`, and `errors` names what uses it. |
| `412` | An `If-Match` names a version the object no longer has; read it again and retry. See [Data formats](/api/formats). |
| `422` | A business rule refuses the request, such as a limit of your plan. |
| `429` | Too many requests; see [Rate limits](/api/rate-limits). |
| `500` | An unexpected error. Quote the `traceId`. |
| `503` | A dependency is briefly unavailable; retry after `Retry-After`. |

## How it behaves

- `retryable` is `true` for `rate_limit_exceeded`, `provider_unavailable` and `external_timeout`. Retry those with a delay; retrying anything else repeats the same answer.
- A `400` from a request body that is not valid JSON, or a field of the wrong type, carries the same shape as one from a failed rule.

## Related

- [Rate limits](/api/rate-limits)
- [Data formats](/api/formats)
- [API reference](/api)
