# Erreurs

> Un document problème lisible par machine pour chaque échec, et ce que chaque type implique pour votre logique de nouvelle tentative.

Source: https://developers.backresto.com/fr/docs/errors

Chaque échec (y compris une route qui n'existe pas) répond en
`application/problem+json`, la forme définie par la RFC 9457. Aucun chemin dans
cette API ne renvoie de page d'erreur HTML : un analyseur qui suppose du JSON
sur une réponse non 2xx est donc en sécurité.

```json
{
  "type": "https://api.backresto.com/problems/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "The authenticated client lacks the required scope.",
  "instance": "/v1/restaurants/restaurant-1/collections/delivery-pictures/records/8f2c/assets",
  "requestId": "b1c8b0a4-6c1e-4f6b-9e1c-3b2a5d7f0e91"
}
```

`type` est l'identifiant stable : branchez dessus, pas sur `detail`, qui est de
la prose et peut être reformulé. `requestId` est la valeur à citer dans un
message au support. Elle est aussi renvoyée dans l'en-tête de réponse
`X-Request-ID`, et vous pouvez définir cet en-tête vous-même pour faire le lien
avec vos propres traces.

## Le catalogue

| Suffixe de `type` | Statut | Ce qui s'est passé | Réessayer ? |
| --- | --- | --- | --- |
| `invalid-request` | 400 | Un paramètre est manquant ou mal formé : un `limit` hors limites, une collection inconnue, ou un curseur qui ne correspond pas au restaurant, à la collection et au `limit` avec lesquels vous paginez. | Non : corrigez la requête. |
| `unauthorized` | 401 | Pas d'en-tête `Authorization`, ou une clé mal formée, inconnue, révoquée, expirée, ou qui n'a plus aucune autorisation. | Non : la clé demande votre attention. |
| `forbidden` | 403 | La clé détient une autorisation pour ce restaurant mais pas le scope dont cet endpoint a besoin. | Non : le client doit faire émettre une clé avec ce scope. |
| `not-found` | 404 | Aucune autorisation pour ce restaurant, ou pas d'enregistrement de ce nom. Les cas sont volontairement indiscernables. | Non. |
| `conflict` | 409 | La requête entre en conflit avec une ressource existante. | Non. |
| `payload-too-large` | 413 | Le corps de la requête dépasse la limite. | Non. |
| `rate-limit-exceeded` | 429 | Votre client a dépassé son budget de requêtes. | Oui, après `Retry-After`. |
| `dependency-unavailable` | 503 | Un composant dont l'API a besoin est brièvement indisponible. | Oui, avec backoff. |
| `internal-error` | 500 | Un échec inattendu, déjà consigné de notre côté. | Une fois, avec backoff ; puis donnez-nous le `requestId`. |

## Ce qu'un client devrait faire

Trois catégories, et rien d'autre ne mérite d'être codé :

**Ne réessayez pas** : 400, 401, 403, 404, 409, 413. La requête échouera de
nouveau à l'identique. Journalisez le `type` et le `requestId`, et faites-le
remonter : un `401` en particulier signifie qu'une personne, du côté de votre
client, a révoqué quelque chose, et une boucle de nouvelles tentatives ne fera
que le masquer pendant une semaine.

**Réessayez avec backoff** : 429, 503. Respectez `Retry-After` sur un 429 ;
c'est le nombre de secondes avant que votre budget ne se recharge, et ce n'est
pas une suggestion. Pour un 503, backoff exponentiel avec jitter, et renoncez
plutôt que de marteler.

**Réessayez une fois, puis escaladez** : 500. Si cela se reproduit sur la même
requête, ce n'est pas transitoire.

Tous les endpoints de cette API sont des `GET`, réessayer est donc toujours sans
danger du point de vue de l'API ; la raison de ne pas réessayer un 4xx est que
cela gaspille votre budget, pas que cela risque une double écriture.

## Faire le lien avec vos propres journaux

Envoyez votre propre identifiant et il vous revient :

```bash
curl "https://api.backresto.com/v1/restaurants/$RESTAURANT_ID/collections/deliveries/records?limit=100" \
  -H "Authorization: Bearer $BACKRESTO_PARTNER_API_KEY" \
  -H "X-Request-ID: 3f7a1c9e-2b4d-4a86-9f0c-5e1d8b6a2c40" \
  --include
```

La valeur est reprise dans l'en-tête de réponse et dans le `requestId` d'un
document problème, ce qui permet à un seul grep de répondre à "qu'a vu
BackResto quand mon job a échoué à 04:12 ?".
