La forme d'une erreur
Toute erreur rend {"error": {"code", "message", "request_id"}}. Le code est en anglais et stable — c'est sur lui qu'un programme décide ; le message est en français et peut changer ; le request_id est ce qu'il faut nous donner pour retrouver un appel (il figure aussi dans l'en-tête X-Request-ID de chaque réponse). Un 401 porte WWW-Authenticate: Bearer.
Les codes
| Code | HTTP | Facturé | Ce que ça veut dire |
|---|---|---|---|
invalid_key | 401 | non | Clé absente, mal formée, inconnue ou révoquée — la même réponse dans les quatre cas. |
api_disabled | 503 | non | L'API n'est pas ouverte sur ce service. |
insufficient_credit | 402 | non | Le solde ne couvre pas l'appel. Rien n'est réservé : rechargez. |
validation_error | 422 | non | Le corps ou le chemin ne respecte pas le schéma ; details dit où. |
rate_limited | 429 | non | Plafond d'appels atteint ; les en-têtes X-RateLimit-* disent quand réessayer. |
too_many_inflight | 429 | non | Une analyse est déjà en cours avec cette clé : attendez son résultat. |
idempotency_in_progress | 409 | non | Un appel portant la même Idempotency-Key travaille encore. |
not_found | 404 | oui pour un diagnostic, non pour une analyse | Diagnostic inconnu du référentiel (le travail a été fait), ou analyse inconnue ou expirée. |
source_unavailable | 503 | non | Une source n'a pas répondu. Le crédit réservé est rendu ; réessayez. |
service_unavailable | 503 | non | Le service ne peut pas répondre pour le moment (mémoire partagée absente, tarif non configuré). Rien n'est débité. |
internal_error | 500 | non | Une faute de notre côté. Le crédit est rendu et l'incident consigné. |
Plafonds
60 appels par minute et par clé, sur une fenêtre fixe, et un plafond par adresse IP qui s'y ajoute — dix clés depuis une même machine ne multiplient pas le débit par dix. Chaque réponse porte X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset (instant Unix où la fenêtre se referme). Au-delà : 429 rate_limited, rien de facturé.
Une analyse à la fois par clé : 429 too_many_inflight pendant qu'une autre travaille. Le service, lui, tient deux analyses d'API en parallèle, à part de celles du site : une agence qui lance ses appels ne prend pas les places des visiteurs.
Ces compteurs vivent dans une mémoire partagée ; si elle se tait, l'API ferme (503) plutôt que de servir — et facturer — à l'aveugle. Rien n'est débité dans ce cas.
Réessayer proprement
- 429 : lisez
X-RateLimit-Resetet attendez ; pourtoo_many_inflight, relisez le résultat en cours par son identifiant plutôt que de relancer. - 503
source_unavailable: le crédit est rendu ; réessayez après quelques secondes, avec la mêmeIdempotency-Keysi vous en aviez une. - Coupure réseau au milieu d'un
POST: renvoyez la même requête avec la mêmeIdempotency-Key— vous recevrez la réponse du premier appel, non facturée, ou 409 s'il travaille encore. - 402 : rien n'a été réservé ; rechargez, puis relancez.
Versions
/v1 est figé : un champ peut s'ajouter à une réponse, jamais s'en retirer ni changer de sens ; un code d'erreur ne change pas de sens. Écrivez votre client pour ignorer les champs qu'il ne connaît pas. Une /v2 garderait /v1 en service un an après son ouverture. Le schéma servi sur /v1/openapi.json est la description qui fait foi ; la référence de cette documentation en est engendrée.