# Paginierung > Releases mit cursor und next_cursor seitenweise lesen, Webhook-Zustellungen mit before und has_more, und nur synchronisieren, was sich geändert hat. Die meisten Listen der API sind kurz und kommen vollständig zurück. Zwei Listen können lang werden und werden seitenweise ausgeliefert: Releases und Webhook-Zustellungen. ## Welche Listen paginiert sind | Endpunkt | Paginierung | Seitengröße | | --- | --- | --- | | `GET /releases` | `cursor` → `next_cursor` | `limit` 1–100, Standard 50 | | `GET /webhooks/{id}/deliveries` | `before` → `has_more` | `limit` 1–100, Standard 50 | | `GET /ddex` | Keine. Ihre letzten 100 Auslieferungen. | 100 | | `GET /members` | Keine. Alle Artists und Labels. | Alle | | `GET /links` | Keine. Alle Smart Links und Pre-Saves. | Alle | | `GET /payouts` | Keine. Alle Auszahlungsanfragen. | Alle | | `GET /webhooks` | Keine. Höchstens 20 Endpunkte. | Alle | | `GET /earnings` | Keine. Gruppiert nach `by` über `months` (1–60). | Alle | ## Releases: Cursor `GET /releases` liefert Releases, die neuesten zuerst. Jede Antwort enthält `next_cursor`. Geben Sie ihn als `cursor` zurück, um die nächste Seite zu erhalten. Auf der letzten Seite ist `next_cursor` gleich `null`. ```bash curl "https://api.hillsmusic.com/v1/releases?limit=100" \ -H "Authorization: Bearer $HILLS_API_KEY" # { "data": [ … ], "next_cursor": "aWQ6ODEy" } curl "https://api.hillsmusic.com/v1/releases?limit=100&cursor=aWQ6ODEy" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` Behandeln Sie den Cursor als undurchsichtige Zeichenkette. Bauen oder verändern Sie ihn nicht selbst. Lassen Sie die übrigen Parameter auf jeder Seite gleich. Filtern Sie die erste Seite mit `status=approved`, senden Sie `status=approved` auch zusammen mit dem Cursor. Ändern Sie einen Filter, beginnen Sie neu ohne Cursor. ### Alle Releases in Node ```js async function* allReleases(params = {}) { let cursor = null; do { const url = new URL("https://api.hillsmusic.com/v1/releases"); for (const [k, v] of Object.entries({ ...params, limit: 100 })) url.searchParams.set(k, v); if (cursor) url.searchParams.set("cursor", cursor); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.HILLS_API_KEY}` }, }); if (!res.ok) throw new Error(`${res.status} ${(await res.json()).code}`); const page = await res.json(); yield* page.data; cursor = page.next_cursor; } while (cursor); } for await (const r of allReleases({ status: "approved" })) { console.log(r.id, r.title, r.delivery_state); } ``` Verwenden Sie für Massenabfragen `limit=100`. Das halbiert die Zahl der Anfragen, die auf Ihr [Rate Limit](https://developer.hillsmusic.com/de/guides/rate-limits/) angerechnet werden. ### Seiten und neue Releases Seiten werden nach Release-ID geschnitten. Ein Release, das während des Blätterns angelegt wird, hat eine höhere ID als die bereits gelesenen und erscheint daher erst auf einer neuen ersten Seite. Duplikate oder Lücken entstehen dadurch nicht. Ein Release, dessen Status sich während des Blätterns ändert, bleibt an seiner Stelle. Filtern Sie nach `status`, kann ein Release zwischen zwei Seiten aus dem Filter herausfallen. Um alles zu erfassen, synchronisieren Sie stattdessen nach Zeit. ## Änderungen synchronisieren Um Ihre eigene Kopie des Katalogs aktuell zu halten, lesen Sie nicht jedes Mal die ganze Liste. Verwenden Sie `updated_since`: 1. Lesen Sie beim ersten Durchlauf alle Seiten. Notieren Sie den Startzeitpunkt in UTC. 2. Senden Sie beim nächsten Durchlauf `updated_since` mit diesem Zeitpunkt und blättern Sie wie gewohnt. 3. Speichern Sie den neuen Startzeitpunkt für den darauffolgenden Durchlauf. ```bash curl "https://api.hillsmusic.com/v1/releases?updated_since=2026-10-18T06:00:00Z&limit=100" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ```js const startedAt = new Date().toISOString(); for await (const r of allReleases({ updated_since: lastRun })) await upsert(r); lastRun = startedAt; // store it ``` `updated_since` erfasst Releases, die zum gesendeten Zeitpunkt oder danach geändert wurden. Ein Release, das genau an der Grenze geändert wurde, kommt deshalb zweimal zurück. Gestalten Sie Ihre Schreibvorgänge idempotent anhand der Release-`id`. Weil Sie den Start- statt den Endzeitpunkt verwenden, wird ein Release, das sich während des Durchlaufs ändert, beim nächsten Mal erneut gelesen. Mit [Webhooks](https://developer.hillsmusic.com/de/guides/webhooks/) reagieren Sie auf Änderungen, sobald sie passieren, und nutzen `updated_since` als nächtlichen Abgleich. ## Webhook-Zustellungen: before `GET /webhooks/{id}/deliveries` liefert, was in den letzten 30 Tagen an einen Endpunkt gesendet wurde, das Neueste zuerst. Die Antwort enthält `has_more`. Ist es `true`, übergeben Sie die ID der letzten Zustellung der Seite als `before`: ```bash curl "https://api.hillsmusic.com/v1/webhooks/7/deliveries?status=failed&limit=100" \ -H "Authorization: Bearer $HILLS_API_KEY" # { "data": [ …, { "id": 1001, … } ], "has_more": true } curl "https://api.hillsmusic.com/v1/webhooks/7/deliveries?status=failed&limit=100&before=1001" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ```js async function failedDeliveries(endpointId) { const out = []; let before = null; for (;;) { const url = new URL(`https://api.hillsmusic.com/v1/webhooks/${endpointId}/deliveries`); url.searchParams.set("status", "failed"); url.searchParams.set("limit", "100"); if (before) url.searchParams.set("before", String(before)); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.HILLS_API_KEY}` }, }); const page = await res.json(); out.push(...page.data); if (!page.has_more || !page.data.length) return out; before = page.data.at(-1).id; } } ``` Sie können nach `status` (`pending`, `succeeded` oder `failed`) und `event` filtern. Lassen Sie die Filter auf jeder Seite gleich. ## Fehler Ein Cursor, der nicht von der API stammt, ergibt `400 invalid` mit `field: "cursor"`. Ein `limit` außerhalb von 1–100 wird nicht abgelehnt, sondern in den gültigen Bereich gebracht: `limit=500` ergibt Seiten mit 100 Einträgen, und ein `limit`, das keine Zahl ist, ergibt den Standardwert 50. Siehe [Fehler](https://developer.hillsmusic.com/de/guides/errors/). Quelle: https://developer.hillsmusic.com/de/guides/pagination/