# Fehler > Das Fehlerformat, alle Status und Codes, die die API zurückgibt, welche Fehler Sie wiederholen sollten, und ein Node-Fehlerhandler zum Übernehmen. Schlägt eine Anfrage fehl, antwortet die API mit einem 4xx- oder 5xx-Status und einem JSON-Body mit einem stabilen `code`. Verzweigen Sie anhand von `code`. Der Text in `error` ist für Menschen gedacht und kann sich ändern. ## Das Format ```json { "error": "This API key doesn't have the earnings:read scope.", "code": "insufficient_scope", "scope": "earnings:read" } ``` | Feld | Immer | Bedeutung | | --- | --- | --- | | `error` | Ja | Was schiefgelaufen ist, in Worten. Kann gefahrlos protokolliert oder Ihrem Betriebsteam angezeigt werden. | | `code` | Ja | Ein stabiler Code. Siehe die Tabellen unten. | | `field` | Bei `invalid` | Der fehlerhafte Parameter oder das fehlerhafte Body-Feld. | | `scope` | Bei `insufficient_scope` | Der Scope, den der Schlüssel braucht. | Einige Fehler enthalten eigene Felder. So listet `409 upload_incomplete` die Teile in `missing` und `wrong_size` auf. ## Fehler, die jeder Endpunkt zurückgeben kann | Status | `code` | Bedeutung | Wiederholen? | | --- | --- | --- | --- | | 400 | `invalid` | Ein Parameter ist fehlerhaft. `field` nennt ihn. | Nein. Korrigieren Sie die Anfrage. | | 401 | `unauthenticated` | Kein Header `Authorization: Bearer`. | Nein | | 401 | `invalid_key` | Der Schlüssel existiert nicht. | Nein | | 401 | `key_revoked` | Der Schlüssel wurde widerrufen. Erstellen Sie einen neuen. | Nein | | 401 | `key_expired` | Der Schlüssel ist abgelaufen. Erstellen Sie einen neuen. | Nein | | 401 | `test_keys_retired` | Ein `hm_test_`-Schlüssel. Eingestellt am 12. Oktober 2026. Verwenden Sie einen `hm_live_`-Schlüssel. | Nein | | 403 | `insufficient_scope` | Dem Schlüssel fehlt der Scope, den dieser Endpunkt braucht. `scope` nennt ihn. | Nein | | 403 | `account_inactive` | Ihr Konto ist nicht aktiv. | Nein | | 403 | `api_not_in_plan` | Ihr Tarif enthält die API nicht. Sie ist Teil von Enterprise und Custom. | Nein | | 404 | `not_found` | Diesen Endpunkt gibt es nicht, oder das Objekt gehört nicht Ihnen. | Nein | | 429 | `rate_limited` | Das Minutenlimit dieses Schlüssels ist überschritten. | Ja, nach `Retry-After` Sekunden | | 500 | `server_error` | Auf unserer Seite ist etwas schiefgelaufen. | Ja, mit Backoff | `404 not_found` steht sowohl für „existiert nicht“ als auch für „gehört einem anderen Konto“. Die API verrät nie, dass ein Release eines anderen Kontos existiert. ## Fehler einzelner Endpunkte | Status | `code` | Wo | Bedeutung | | --- | --- | --- | --- | | 409 | `exists` | `POST /members/invite` | Für diese E-Mail-Adresse gibt es bereits ein Konto. | | 413 | `too_large` | `POST /ddex/validate` | Größer, als ein Test verarbeitet. Liefern Sie ihn mit `POST /ddex`. | | 413 | `too_large` | `POST /ddex` | Über 20 GB (Raw-Body) oder 512 MB (Multipart). Verwenden Sie einen Direkt-Upload. | | 429 | `busy` | `POST /ddex/validate` | Zu viele Tests gleichzeitig. Versuchen Sie es gleich noch einmal. | | 409 | `upload_incomplete` | `POST /ddex/uploads/{id}/commit` | Teile fehlen oder haben die falsche Größe. Laden Sie sie hoch und committen Sie erneut. | | 409 | `already_committed` | Direkt-Uploads | Bereits committet. `status_url` verweist auf die Auslieferung. | | 409 | `commit_in_progress` | `POST /ddex/uploads/{id}/commit` | Ein anderer Commit dieses Uploads läuft. | | 400 | `invalid_url` | `POST /webhooks`, `PATCH /webhooks/{id}` | Keine öffentliche https-URL auf Port 443. | | 409 | `too_many` | `POST /webhooks` | Sie haben bereits 20 Endpunkte. | | 409 | `endpoint_disabled` | Test und Wiederholung von Webhooks | Der Endpunkt ist deaktiviert. Schalten Sie ihn zuerst ein. | Jede [Referenzseite](https://developer.hillsmusic.com/de/reference/releases/) listet die Fehler ihrer Endpunkte auf. Die gemeinsamen stehen unter [Scopes und Fehler](https://developer.hillsmusic.com/de/reference/scopes-and-errors/). ## Validierungsfehler Ein `400 invalid` nennt das erste gefundene Problem: ```json { "error": "updated_since is an ISO date or time.", "code": "invalid", "field": "updated_since" } ``` Es wird immer nur ein Feld gemeldet. Korrigieren Sie es und senden Sie die Anfrage erneut. Wenn Sie ein Formular auf der API aufbauen, zeigen Sie `error` neben dem Eingabefeld an, das `field` nennt. Bei DDEX-Dateien ist das anders. Ein DDEX-Batch mit Problemen ergibt kein `400`. Der Test antwortet mit `200`, allen Prüfungen und einem Ergebnis, und eine Auslieferung antwortet mit `202` und meldet Probleme pro Release. Siehe [DDEX-Auslieferung](https://developer.hillsmusic.com/de/guides/ddex/). ## Was Sie wiederholen sollten - **Wiederholen** Sie `429` und `5xx` sowie Netzwerkfehler wie Timeouts und abgebrochene Verbindungen. - **Nicht wiederholen** sollten Sie andere `4xx`. Dieselbe Anfrage erhält dieselbe Antwort. Korrigieren Sie zuerst die Anfrage, den Schlüssel oder seine Scopes. Warten Sie bei `429` so viele Sekunden, wie `Retry-After` angibt. Warten Sie bei `5xx` nach jedem Versuch länger (1 s, 2 s, 4 s …) und geben Sie nach einigen Versuchen auf. Siehe [Rate Limits](https://developer.hillsmusic.com/de/guides/rate-limits/). Lesezugriffe können Sie gefahrlos wiederholen. Bei Schreibzugriffen sollten Sie vorher nachdenken: Ein wiederholtes `POST /ddex` nach einer verlorenen Antwort kann den Batch zweimal einreihen. Prüfen Sie zuerst mit `GET /ddex`, ob er schon da ist. ## Ein Node-Fehlerhandler ```js 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; } ``` Mit curl sehen Sie den Status mit `-w '%{http_code}'`, die Header mit `-i`: ```bash curl -i "https://api.hillsmusic.com/v1/releases/999999" \ -H "Authorization: Bearer $HILLS_API_KEY" # HTTP/2 404 # {"error":"…","code":"not_found"} ``` Quelle: https://developer.hillsmusic.com/de/guides/errors/