# Errors

https://gorally.games/en/developers/errors

When a request fails, the API answers with an HTTP status and a JSON body of three fields.

```json
{
  "error": "Cette clé est inconnue, révoquée ou expirée.",
  "code": "UNAUTHORIZED",
  "request_id": "9f2c41d7a3b54e0c"
}
```

- `error`: a human-readable message, in French. It may change: never compare it.
- `code`: a stable code. Build your logic on it.
- `request_id`: the request’s identifier.

The API’s error messages are in French only, including on the English documentation. Use `code` to show your own message.

## Headers to read

- `X-Request-Id`: present on every response, successes included. It equals `request_id`. Include it when you write to us: it is what finds your request in our logs. You can also send your own, 8 to 64 characters from `A-Za-z0-9_.:-`.
- `Retry-After`: the number of seconds to wait before retrying. It comes with `RATE_LIMITED` and `LEAGUES_UNAVAILABLE`.

## The codes

| Code | Status | Cause | What to do |
|---|---|---|---|
| `INVALID_INPUT` | `400` | Malformed request: missing field, out-of-range value, unreadable body. | Fix the request based on `error`, which names the field when it can. |
| `UNAUTHORIZED` | `401` | Missing, malformed, unknown, revoked or expired key. | Check the `Authorization` header. If the key was revoked, issue a new one. |
| `FORBIDDEN` | `403` | The key lacks the operation’s scope. | Issue a key with the right scope. |
| `ENTITLEMENT_DENIED` | `403` | The organization’s subscription does not allow this access. | Check the organization’s Leagues plan. |
| `NOT_FOUND` | `404` | The item does not exist in the key’s organization, or the route does not exist. | Check the identifier and the path. |
| `CONFLICT` | `409` | The revision you sent is stale, or the item no longer accepts this command. | Read the item again, then decide. Do not retry blindly. |
| `IDEMPOTENCY_KEY_REUSED` | `409` | This `Idempotency-Key` was already used with a different body. | Use a new key for a new request. |
| `IDEMPOTENT_REQUEST_IN_FLIGHT` | `409` | A request with this `Idempotency-Key` is still running. | Retry in a moment, with the same key. |
| `IDEMPOTENCY_OUTCOME_UNKNOWN` | `409` | A request with this `Idempotency-Key` was interrupted with an unknown outcome. | Read the item again to know whether it was created, then resume with a new key. |
| `ROTATION_EN_COURS` | `409` | A secret rotation on this endpoint is already in its grace period. | Wait for the grace period to end, or rotate with an immediate cut-off. |
| `BODY_TOO_LARGE` | `413` | The body is over 16 KiB. | Shrink the body. The API carries no files. |
| `RATE_LIMITED` | `429` | Too many requests, from your address or with your key. | Wait `Retry-After` seconds, then resume with jittered exponential backoff. |
| `LEAGUES_UNAVAILABLE` | `503` | Temporary outage, or a request longer than 10 seconds. | Wait `Retry-After` seconds. After a write, check its state before repeating it. |
| `ENTITLEMENT_UNAVAILABLE` | `503` | The organization’s entitlement cannot be checked right now. | Retry later, with backoff. |
| `HOLDER_UNINITIALIZED` | `503` | The organization has not yet named its subscription holder. | Ask someone who manages the organization to name one. |
| `WEBHOOK_VAULT_UNAVAILABLE` | `503` | Webhooks are not configured on this server. | Write to us: it is not a setting of your organization. |

`ROTATION_EN_COURS` and `WEBHOOK_VAULT_UNAVAILABLE` come from webhook management, in the Integrations screen. You will rarely meet them through the API.

## Retry or not

- `4xx`: the request is at fault. Fix it before sending it again, except for `429` and `IDEMPOTENT_REQUEST_IN_FLIGHT`.
- `5xx`: Rally is at fault. Retry with jittered exponential backoff.
- On a `POST`, send an `Idempotency-Key`. A new attempt then replays the original response for 24 hours, without duplicates.

If you get a `code` your software does not know, handle it based on the HTTP status.
