Erreurs et limites de requêtes
Tous les endpoints signalent les échecs sous la même forme, avec un code lisible par machine et un ID de requête.
Réponse d'erreur
Un appel en échec renvoie success: false. code est stable et destiné aux programmes, error est un court message en anglais destiné aux humains, et request_id identifie l'appel dans nos journaux. param désigne le paramètre en cause lorsque le problème vient d'une entrée.
Exemples réels
Ce sont des réponses en direct, récupérées auprès de l'API au moment du rendu de cette page.
{
"success": false,
"error": "coin required",
"code": "INVALID_PARAM",
"request_id": "cb-mwefukvc-5ba0c25193"
}{
"success": false,
"code": "NOT_FOUND",
"error": "unknown endpoint: GET /api/this-endpoint-does-not-exist",
"request_id": "cb-mwefukvd-003852f270"
}Codes d'erreur
| Code | HTTP | Signification | Que faire |
|---|---|---|---|
| INVALID_PARAM | 400 | Un paramètre requis est manquant ou une valeur n'est pas acceptée. `param` indique le nom du paramètre lorsqu'il est connu. | Ne réessayez pas à l'identique ; corrigez la requête. |
| UNAUTHORIZED | 401 | L'en-tête `CB-API-KEY` a été envoyé, mais la clé est inconnue ou révoquée. Les données publiques ne nécessitent aucune clé — supprimez l'en-tête ou utilisez une clé valide. | Ne réessayez pas à l'identique. |
| FORBIDDEN | 403 | La route ne fait pas partie de l'API publique (interne ou réservée aux comptes). | Ne réessayez pas. |
| NOT_FOUND | 404 | Route inconnue, ou la crypto / la plateforme / le fonds demandé n'existe pas. | Ne réessayez pas ; vérifiez le chemin et les identifiants dans le catalogue. |
| RATE_LIMITED | 429 | Plus de requêtes que la limite par minute. `Retry-After` indique le nombre de secondes à attendre. | Attendez la durée indiquée par `Retry-After`, puis réessayez avec backoff. |
| INTERNAL | 500 | Erreur serveur inattendue. Le message est volontairement générique ; citez `request_id` lorsque vous la signalez. | Réessayez une fois après quelques secondes ; si l'erreur persiste, signalez-la avec l'ID de requête. |
| UPSTREAM_FAILED | 503 | La source de données derrière cet endpoint n'a pas répondu à temps. Aucun chiffre périmé ni de substitution n'est renvoyé à sa place. | Réessayez avec backoff ; consultez la page de statut. |
| UNAVAILABLE | 501 / 503 | Le jeu de données n'est temporairement pas prêt (préchauffage du cache) ou l'endpoint n'a pas encore de source publique licite. | Réessayez plus tard ; le catalogue signale les endpoints indisponibles par conception. |
| REQUEST_FAILED | 200 | Certains endpoints plus anciens répondent HTTP 200 avec `success: false`. Vérifiez toujours `success`, et pas seulement le statut HTTP. | Dépend du message ; à traiter comme une requête en échec. |
ID de requête
Chaque réponse porte un en-tête X-Request-Id. Les réponses en échec le reprennent dans le corps sous request_id. Les réponses servies depuis le cache court en périphérie reprennent l'ID de la requête qui les a produites : des ID identiques sur des appels consécutifs signifient donc que vous avez reçu une copie en cache.
Limites de requêtes
Les limites s'appliquent par minute, par adresse IP pour les appels anonymes et par clé lorsqu'un en-tête CB-API-KEY valide est envoyé. La limite est de 1200 requêtes par minute. Les requêtes d'icônes sous /api/coin-icon ne sont pas décomptées.
En-têtes de limite de requêtes
| Nom | Description |
|---|---|
| X-Request-Id | Identifiant de cette requête. Citez-le dans vos rapports de bug. |
| X-RateLimit-Limit | Nombre de requêtes autorisées dans la fenêtre d'une minute en cours. |
| X-RateLimit-Remaining | Requêtes restantes dans la fenêtre en cours. |
| X-RateLimit-Reset | Heure Unix, en secondes, à laquelle la fenêtre est réinitialisée. |
| Retry-After | Envoyé avec HTTP 429 : nombre de secondes à attendre avant de réessayer. |
| X-Cache | HIT, STALE ou MISS pour le cache de réponses côté serveur. |
En cas de dépassement de la limite
L'API répond HTTP 429 avec le code RATE_LIMITED. Attendez le nombre de secondes indiqué dans Retry-After, puis réessayez. Interroger un endpoint plus souvent que le TTL de son cache renvoie la même réponse en cache : alignez donc votre intervalle d'interrogation sur le TTL indiqué sur chaque page de référence.
Réessayer avec backoff
async function getJson(url, tries = 4) {
for (let i = 0; i < tries; i++) {
const res = await fetch(url);
if (res.status === 429 || res.status >= 500) {
const wait = Number(res.headers.get("Retry-After")) || 2 ** i;
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
const body = await res.json();
if (body.success === false) {
throw new Error(body.code + ": " + body.error + " (" + body.request_id + ")");
}
return body;
}
throw new Error("gave up after " + tries + " attempts");
}L'absence de données n'est pas une erreur
Lorsque les paramètres sont valides mais qu'il n'existe aucune source publique licite pour les données, l'appel réussit avec HTTP 200 : les champs de valeur valent null, meta.quality vaut UNAVAILABLE et coverage.unavailable en donne la raison. Affichez un tiret. Ne convertissez pas la valeur en 0.
Données périmées
Si un collecteur prend du retard, les endpoints continuent de servir les dernières valeurs stockées avec meta.is_stale: true jusqu'à ce qu'elles sortent de la fenêtre exploitable ; elles sont alors retirées des agrégats et listées dans coverage.stale_excluded.