# Errors

Every error code the API returns, with what it means and what your integration should do.

Errors use `application/problem+json` ([RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)):

```json
{
  "type": "https://docs.kapiworks.com/errors/invalid_token",
  "title": "Invalid API key",
  "status": 401,
  "detail": "The API key is invalid or no longer active.",
  "code": "invalid_token"
}
```

Act on `code`, or on `type`, which is the address of the code's page here. They are stable. `title` and `detail` are for people and can change, so do not parse them.

## Every code

| Status | Code | What to do |
| --- | --- | --- |
| 400 | [`invalid_request`](https://docs.kapiworks.com/errors/invalid_request) | Fix the query and send it again. Unknown or repeated parameters, malformed dates and IDs, and periods longer than 400 days are refused. |
| 400 | [`invalid_cursor`](https://docs.kapiworks.com/errors/invalid_cursor) | Start the pull again without a cursor. A cursor works only on the endpoint and filters that produced it, for the same company. |
| 400 | [`key_in_url`](https://docs.kapiworks.com/errors/key_in_url) | A URL can be stored in logs and browser history. Ask the company administrator for a new key, and send it only in the Authorization header. |
| 401 | [`invalid_token`](https://docs.kapiworks.com/errors/invalid_token) | Stop polling and ask the company administrator for a new key. Unknown, expired and revoked keys get the same answer. |
| 403 | [`insufficient_scope`](https://docs.kapiworks.com/errors/insufficient_scope) | Ask the company administrator for a key with the scope named in the WWW-Authenticate header. Retrying the same key does not help. |
| 403 | [`ip_not_allowed`](https://docs.kapiworks.com/errors/ip_not_allowed) | Call from one of the key's networks, or ask the company administrator for a key that allows yours. |
| 404 | [`not_found`](https://docs.kapiworks.com/errors/not_found) | Use a documented path on the API host. |
| 405 | [`method_not_allowed`](https://docs.kapiworks.com/errors/method_not_allowed) | The API is read-only. The Allow header lists the methods it accepts. |
| 422 | [`before_history`](https://docs.kapiworks.com/errors/before_history) | Use history_complete_from as the earliest moment you ask for. Earlier records are unavailable, not empty. |
| 422 | [`record_too_large`](https://docs.kapiworks.com/errors/record_too_large) | Use a records pack for this register, and report the request ID to Kapi support. |
| 429 | [`rate_limited`](https://docs.kapiworks.com/errors/rate_limited) | Wait at least Retry-After seconds, then add a small random delay. Refused calls do not count against the limit. |
| 429 | [`concurrent_limit`](https://docs.kapiworks.com/errors/concurrent_limit) | Wait for the running calls to finish, then retry after Retry-After seconds. Run one pull at a time per company. |
| 502 | [`read_failed`](https://docs.kapiworks.com/errors/read_failed) | Keep your last complete pull. Retry with exponential backoff, and report the request ID if it keeps failing. |
| 503 | [`unavailable`](https://docs.kapiworks.com/errors/unavailable) | Contact Kapi support with the request ID. Retrying does not help until the configuration is fixed. |
| 503 | [`upstream_unavailable`](https://docs.kapiworks.com/errors/upstream_unavailable) | Retry after Retry-After seconds with exponential backoff and jitter. Keep your last complete pull meanwhile. |
| 503 | [`writer_unavailable`](https://docs.kapiworks.com/errors/writer_unavailable) | Retry after Retry-After seconds. A pull already in progress can still finish from its cursor. |
| 504 | [`read_timeout`](https://docs.kapiworks.com/errors/read_timeout) | Retry with a smaller limit, then return to your usual page size. |

## Headers that come with errors

* `X-Request-Id` on every error. Quote it when you [contact support](https://docs.kapiworks.com/support), without the key.
* `WWW-Authenticate` on 401 and 403 scope refusals. A scope refusal names the scope it needs.
* `Retry-After` on 429 and 503: wait at least that many seconds.
* `Allow` on 405, listing `GET, HEAD`.

## Retrying

Retry connection failures and statuses 429, 502, 503 and 504, at most five times, with delays such as 1, 2, 4, 8 and 16 seconds plus a little random jitter. `Retry-After` takes precedence over your own delay. Use a timeout on every request, and when retries stop, report a failed sync instead of an empty result.

Do not retry 400, 401, 403, 404, 405 or 422 without changing something: the same request gets the same answer. Retrying a `GET` is safe, because reading creates no records.
