Erreurs
Un document problème lisible par machine pour chaque échec, et ce que chaque type implique pour votre logique de nouvelle tentative.
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é.
{
"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 :
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 ?".