# DDEX-Auslieferung > Releases als DDEX ERN senden: Batch mit POST /ddex/validate testen, mit POST /ddex oder Direkt-Uploads liefern, SFTP nutzen und den Lieferbericht lesen. Releases kommen als DDEX-ERN-Batches zu HILLS Music. Einzelne Releases Feld für Feld anlegen oder bearbeiten kann die API nicht. Sie senden denselben Batch, den Sie auch an einen Store senden würden, per API oder SFTP. Jedes darin enthaltene Release wird ein Entwurf in Ihrem Katalog und durchläuft wie gewohnt Prüfung und Auslieferung an die Stores. ## ERN-Versionen | Version | Status | | --- | --- | | ERN 4.3 (`http://ddex.net/xml/ern/43`) | Empfohlen | | 4.2, 4.1 | Akzeptiert | | 3.8.2, 3.8.1, 3.8, 3.7 | Akzeptiert. Der Bericht weist auf die veraltete Version hin. | | Alle anderen | Abgelehnt | Jede akzeptierte Version durchläuft dieselben Prüfungen und denselben Import. Ein Batch ist eine ZIP-Datei mit einer oder mehreren `NewReleaseMessage`-XML-Dateien und den Audiodateien, Covern und Videos, auf die sie verweisen. ## Scopes | Scope | Erlaubt | | --- | --- | | `ddex:validate` | Nur Tests. Gut geeignet für CI. | | `ddex:write` | Tests, Auslieferungen, Direkt-Uploads und Auslieferungsstatus. | ## 1. Zuerst testen `POST /ddex/validate` durchläuft jede Prüfung, die auch eine Auslieferung durchläuft: das XML, die HILLS-Regeln, die Audio-, Artwork- und Videodateien, UPCs und ISRCs im Abgleich mit Ihrem Katalog, Genres, Territorien und Deals. **Es wird nichts angelegt**: kein Release, keine Aufnahme, kein Artist, kein Code und keine Auslieferung. Senden Sie eine `.zip` oder eine einzelne `.xml`. ```bash curl -X POST "https://api.hillsmusic.com/v1/ddex/validate?member_id=41" \ -H "Authorization: Bearer $HILLS_API_KEY" \ -H "Content-Type: application/zip" \ --data-binary @batch-0001.zip ``` ```js import { readFile } from "node:fs/promises"; const res = await fetch("https://api.hillsmusic.com/v1/ddex/validate?member_id=41", { method: "POST", headers: { Authorization: `Bearer ${process.env.HILLS_API_KEY}`, "Content-Type": "application/zip" }, body: await readFile("batch-0001.zip"), }); const { data } = await res.json(); console.log(data.verdict, data.summary); for (const c of data.checks.filter((c) => c.status === "error")) console.log(c.field, c.message); ``` `member_id` ist der Artist oder das Label, für den der Batch bestimmt ist. Lassen Sie den Parameter für Ihren eigenen Katalog weg. Für eine XML-Datei senden Sie `Content-Type: application/xml`. Sie können auch `multipart/form-data` mit dem Feld `file` senden (bis 512 MB). Die Antwort enthält die ERN-Version, eine Zusammenfassung, jede Prüfung nach Phase (`pass`, `warning`, `error`, `skipped`) und ein Ergebnis: | Ergebnis | Bedeutung | | --- | --- | | `would_import` | Fehlerfrei. Würde als Entwurf angelegt. | | `would_import_with_warnings` | Würde importiert. Lesen Sie die Warnungen. | | `would_be_flagged` | Würde auf das HILLS-Team warten: ein Takedown oder ein Update eines Releases, das in Prüfung oder live ist. | | `would_be_rejected` | Enthält Fehler. Für dieses Release würde nichts angelegt. | Auch ein Batch mit Fehlern antwortet mit `200`; das Ergebnis sagt, was nicht stimmt. Ein Batch, der für einen Test zu groß ist, antwortet mit `413 too_large`, und viele gleichzeitige Tests können `429 busy` ergeben. Jeder Test erscheint außerdem 90 Tage lang auf der DDEX-Seite der Web-App unter **Test reports**. ## 2. Liefern `POST /ddex` nimmt die ZIP-Datei als Raw-Body (`Content-Type: application/zip`, bis 20 GB) oder im Multipart-Feld `file` (bis 512 MB) entgegen. Der Endpunkt antwortet sofort mit `202`: ```bash curl -X POST "https://api.hillsmusic.com/v1/ddex?member_id=41&name=batch-0001.zip" \ -H "Authorization: Bearer $HILLS_API_KEY" \ -H "Content-Type: application/zip" \ --data-binary @batch-0001.zip # {"data":{"id":311,"status":"queued","environment":"production","status_url":"/v1/ddex/311"}} ``` Für große Dateien ist ein Direkt-Upload die bessere Wahl. ## Direkt-Uploads für große Batches Bei einem Direkt-Upload geht die Datei direkt in den Speicher statt über die API. 1. **Starten.** `POST /ddex/uploads` mit `name` und `size` in Bytes (bis 20 GB), bei Bedarf mit `member_id`. 2. **Hochladen.** Bis 64 MB erhalten Sie eine `upload.url`: Senden Sie die ganze Datei per `PUT` dorthin. Über 64 MB erhalten Sie `upload.part_size` und eine URL pro Teil. Senden Sie jeden Abschnitt von `part_size` Bytes per `PUT` an seine URL (der letzte Abschnitt ist kürzer). Die Teile können in beliebiger Reihenfolge und parallel hochgeladen werden. Diese URLs sind signiert: Senden Sie an sie keinen `Authorization`-Header. 3. **Committen.** `POST /ddex/uploads/{id}/commit`. Der Endpunkt prüft, ob jeder Teil in der richtigen Größe angekommen ist, und reiht den Batch dann wie `POST /ddex` ein (`202`). ```js import { open, stat } from "node:fs/promises"; const H = { Authorization: `Bearer ${process.env.HILLS_API_KEY}`, "Content-Type": "application/json" }; const API = "https://api.hillsmusic.com/v1"; const file = "batch-0001.zip"; const { size } = await stat(file); const start = await fetch(`${API}/ddex/uploads`, { method: "POST", headers: H, body: JSON.stringify({ name: file, size, member_id: 41 }), }).then((r) => r.json()); const { id, upload } = start.data; const fh = await open(file); if (upload.url) { await fetch(upload.url, { method: "PUT", body: await fh.readFile() }); } else { for (const p of upload.parts) { const offset = (p.part_number - 1) * upload.part_size; const buf = Buffer.alloc(Math.min(upload.part_size, size - offset)); await fh.read(buf, 0, buf.length, offset); const r = await fetch(p.url, { method: "PUT", body: buf }); if (!r.ok) throw new Error(`part ${p.part_number}: ${r.status}`); } } await fh.close(); const commit = await fetch(`${API}/ddex/uploads/${id}/commit`, { method: "POST", headers: H }); console.log(commit.status, await commit.json()); // 202, then poll status_url ``` Die URLs für die Teile gelten 6 Stunden. `GET /ddex/uploads/{id}` liefert neue URLs für die noch fehlenden Teile, zusammen mit `received_parts` und `parts_total`. Ein Commit mit fehlenden Teilen antwortet mit `409 upload_incomplete` und listet `missing` und `wrong_size` auf: Senden Sie diese Teile und committen Sie erneut. `DELETE /ddex/uploads/{id}` verwirft einen Upload, den Sie nicht abschließen. Nicht committete Uploads werden nach 7 Tagen entfernt. ## Per SFTP Jede DDEX-Inbox ist ein SFTP-Login mit zwei Ordnern. Den Login erhalten Sie zusammen mit Ihrer Inbox auf der DDEX-Seite der Web-App. | Ordner | Was passiert | | --- | --- | | `/production//` | Wird geliefert. Sobald die Markerdatei eintrifft, wird der Batch importiert. | | `/test//` | Wird getestet, wie mit `POST /ddex/validate`. Es wird nichts angelegt. Der Bericht wird daneben abgelegt: `/test/.report.txt` und `.report.json`. | Laden Sie das XML und seine Dateien in den Batch-Ordner hoch und zuletzt die Markerdatei: `BatchComplete_*.xml` oder eine beliebige `*.complete`-Datei. Eine einzelne `/test/.xml` oder `.zip` wird ebenfalls getestet. Jede andere Datei in `/test`, etwa `ping.txt`, gilt als Verbindungstest. Ein Produktions-Batch-Ordner, der nie seine Markerdatei erhält, wird nach 7 Tagen entfernt; alles, was in `/test` liegt, nach derselben Frist. Siehe [Testordner](https://developer.hillsmusic.com/de/reference/test-folder/). ## 3. Den Lieferbericht lesen Fragen Sie `GET /ddex/{id}` alle 10–30 Sekunden ab oder abonnieren Sie den [Webhook](https://developer.hillsmusic.com/de/guides/webhooks/) `ddex.import.imported`. Der Status durchläuft `queued` → `parsing` → `validating` → `importing` und endet dann mit: - `done`: Alle Releases sind angekommen; - `partial`: Einige Releases wurden ausgelassen; - `failed`: Es wurde nichts importiert. ```bash curl "https://api.hillsmusic.com/v1/ddex/311" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` Die Antwort enthält Zählwerte und einen Eintrag pro Release, jeweils mit `outcome`, `release_id` und `errors` (jeder Fehler nennt sein DDEX-Feld). `GET /ddex` listet Ihre letzten 100 Auslieferungen auf. ## Was angelegt oder markiert wird | Outcome | Wann | | --- | --- | | `created` | Ein neues Release. Es wird ein Entwurf im Katalog von `member_id`. | | `updated` | Die UPC existiert dort bereits als Entwurf (oder als zur Überarbeitung zurückgegebenes Release). Dieser Entwurf wird aktualisiert. | | `flagged` | Ein Takedown oder ein Update eines Releases, das in Prüfung oder live ist. Es wird nicht übernommen, sondern vom HILLS-Team geprüft. | | `left_out` | Das Release enthielt Fehler. Dafür wurde nichts angelegt. Korrigieren Sie es und liefern Sie erneut. | | `test` | Eine als `TestMessage` gekennzeichnete Nachricht: geprüft, nichts angelegt. | Eine ISRC, die Sie bereits haben, verwendet die vorhandene Aufnahme weiter. Eine ISRC, die zu einem anderen Konto gehört, führt dazu, dass das Release ausgelassen wird. Entwürfe durchlaufen anschließend wie gewohnt die Prüfung: Reichen Sie sie in der Web-App ein oder bitten Sie HILLS Music, für Ihre Inbox die automatische Einreichung zu aktivieren. Verfolgen Sie sie mit [GET /releases](https://developer.hillsmusic.com/de/reference/releases/) und Webhooks wie `release.approved` und `release.live`. Alle Parameter finden Sie in der [Referenz zu DDEX-Auslieferungen](https://developer.hillsmusic.com/de/reference/ddex-deliveries/). Quelle: https://developer.hillsmusic.com/de/guides/ddex/