Erreurs
Le format des erreurs, tous les statuts et codes renvoyés par l’API, les erreurs à retenter, et un gestionnaire d’erreurs Node prêt à copier.
Mis à jour le
Quand une requête échoue, l’API renvoie un statut 4xx ou 5xx et un corps JSON avec un code stable. Basez votre logique sur code. Le texte de error s’adresse à des personnes et peut changer.
Le format
{
"error": "This API key doesn't have the earnings:read scope.",
"code": "insufficient_scope",
"scope": "earnings:read"
}
| Champ | Toujours présent | Signification |
|---|---|---|
error |
Oui | Ce qui s’est mal passé, en toutes lettres. Peut être journalisé ou affiché à un opérateur sans risque. |
code |
Oui | Un code stable. Voir les tableaux ci-dessous. |
field |
Avec invalid |
Le paramètre ou le champ du corps en cause. |
scope |
Avec insufficient_scope |
Le scope dont la clé a besoin. |
Quelques erreurs ajoutent leurs propres champs. Par exemple, 409 upload_incomplete liste les parties missing et wrong_size.
Erreurs possibles sur tous les endpoints
| Statut | code |
Signification | Retenter ? |
|---|---|---|---|
| 400 | invalid |
Un paramètre est incorrect. field l’indique. |
Non. Corrigez la requête. |
| 401 | unauthenticated |
Aucun en-tête Authorization: Bearer. |
Non |
| 401 | invalid_key |
La clé n’existe pas. | Non |
| 401 | key_revoked |
La clé a été révoquée. Créez-en une nouvelle. | Non |
| 401 | key_expired |
La clé a expiré. Créez-en une nouvelle. | Non |
| 401 | test_keys_retired |
Une clé hm_test_, retirée le 12 octobre 2026. Utilisez une clé hm_live_. |
Non |
| 403 | insufficient_scope |
La clé n’a pas le scope requis par cet endpoint. scope l’indique. |
Non |
| 403 | account_inactive |
Votre compte n’est pas actif. | Non |
| 403 | api_not_in_plan |
Votre offre n’inclut pas l’API. Elle est incluse dans Enterprise et Custom. | Non |
| 404 | not_found |
Endpoint inexistant, ou ressource qui ne vous appartient pas. | Non |
| 429 | rate_limited |
Limite par minute de cette clé dépassée. | Oui, après Retry-After secondes |
| 500 | server_error |
Un problème est survenu de notre côté. | Oui, avec un délai croissant |
404 not_found couvre à la fois « n’existe pas » et « appartient à un autre compte ». L’API ne vous révèle jamais l’existence de la sortie de quelqu’un d’autre.
Erreurs propres à certains endpoints
| Statut | code |
Où | Signification |
|---|---|---|---|
| 409 | exists |
POST /members/invite |
Un compte existe déjà avec cette adresse e-mail. |
| 413 | too_large |
POST /ddex/validate |
Trop volumineux pour un test. Livrez-le avec POST /ddex. |
| 413 | too_large |
POST /ddex |
Plus de 20 Go (corps brut) ou de 512 Mo (multipart). Utilisez un envoi direct. |
| 429 | busy |
POST /ddex/validate |
Trop de tests simultanés. Réessayez dans un instant. |
| 409 | upload_incomplete |
POST /ddex/uploads/{id}/commit |
Parties manquantes ou de mauvaise taille. Envoyez-les, puis finalisez à nouveau. |
| 409 | already_committed |
Envois directs | Déjà finalisé. status_url pointe vers la livraison. |
| 409 | commit_in_progress |
POST /ddex/uploads/{id}/commit |
Une autre finalisation de cet envoi est en cours. |
| 400 | invalid_url |
POST /webhooks, PATCH /webhooks/{id} |
Pas une URL https publique sur le port 443. |
| 409 | too_many |
POST /webhooks |
Vous avez déjà 20 endpoints. |
| 409 | endpoint_disabled |
Test et nouvelle tentative de webhook | L’endpoint est désactivé. Réactivez-le d’abord. |
Chaque page de la référence liste les erreurs de chaque endpoint. Scopes et erreurs regroupe les erreurs communes.
Erreurs de validation
Une 400 invalid désigne le premier problème rencontré :
{
"error": "updated_since is an ISO date or time.",
"code": "invalid",
"field": "updated_since"
}
Un seul champ est signalé à la fois. Corrigez-le et renvoyez la requête. Si vous construisez un formulaire au-dessus de l’API, affichez error à côté du champ désigné par field.
Les fichiers DDEX fonctionnent autrement. Un lot DDEX qui pose problème ne renvoie pas de 400. Le test renvoie 200 avec toutes les vérifications et un verdict, et une livraison renvoie 202 puis signale les problèmes sortie par sortie. Voir Livraison DDEX.
Quoi retenter
- Retentez les
429et les5xx, ainsi que les erreurs réseau comme les délais dépassés et les connexions réinitialisées. - Ne retentez pas les autres
4xx. La même requête obtiendra la même réponse. Corrigez d’abord la requête, la clé ou ses scopes.
Pour une 429, attendez le nombre de secondes indiqué dans Retry-After. Pour une 5xx, attendez plus longtemps après chaque essai (1 s, 2 s, 4 s…) et abandonnez au bout de quelques tentatives. Voir Limites de débit.
Les lectures peuvent être retentées sans risque. Réfléchissez avant de retenter une écriture : un POST /ddex relancé après une réponse perdue peut mettre le lot deux fois en file d’attente. Vérifiez d’abord sa présence avec GET /ddex.
Un gestionnaire d’erreurs Node
export class HillsError extends Error {
constructor(status, body, headers) {
super(body.error ?? `HTTP ${status}`);
this.status = status;
this.code = body.code;
this.field = body.field;
this.scope = body.scope;
this.retryAfter = Number(headers.get("Retry-After")) || null;
}
}
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
export async function hills(path, init = {}, tries = 4) {
for (let i = 1; ; i++) {
const res = await fetch("https://api.hillsmusic.com/v1" + path, {
...init,
headers: { ...init.headers, Authorization: `Bearer ${process.env.HILLS_API_KEY}` },
});
const body = await res.json().catch(() => ({}));
if (res.ok) return body;
const err = new HillsError(res.status, body, res.headers);
const retryable = res.status === 429 || res.status >= 500;
if (!retryable || i >= tries) throw err;
await sleep(err.retryAfter ? err.retryAfter * 1000 : 1000 * 2 ** (i - 1));
}
}
try {
await hills("/earnings");
} catch (err) {
if (err.code === "insufficient_scope") console.error(`Add ${err.scope} to this key.`);
else if (err.code === "api_not_in_plan") console.error("The plan doesn't include the API.");
else throw err;
}
Avec curl, ajoutez -w '%{http_code}' pour voir le statut, ou -i pour voir les en-têtes :
curl -i "https://api.hillsmusic.com/v1/releases/999999" \
-H "Authorization: Bearer $HILLS_API_KEY"
# HTTP/2 404
# {"error":"…","code":"not_found"}