Aller au contenu
API HILLS v1 Accès anticipé

Guides

Livraison DDEX

Livrez en DDEX ERN : testez un lot avec POST /ddex/validate, livrez avec POST /ddex ou l’envoi direct, passez par le SFTP et lisez le rapport.

Mis à jour le

Les sorties entrent dans HILLS Music sous forme de lots DDEX ERN. L’API ne crée ni ne modifie de sorties à l’unité, champ par champ. Vous envoyez le même lot que celui que vous enverriez à une plateforme, via l’API ou en SFTP. Chaque sortie qu’il contient devient un brouillon dans votre catalogue, puis passe par la vérification et la livraison aux plateformes comme d’habitude.

Versions ERN

Version Statut
ERN 4.3 (http://ddex.net/xml/ern/43) Recommandée
4.2, 4.1 Acceptées
3.8.2, 3.8.1, 3.8, 3.7 Acceptées. Le rapport signale que la version est ancienne.
Toute autre version Refusée

Toutes les versions acceptées passent par les mêmes vérifications et le même import. Un lot est un zip contenant un ou plusieurs fichiers XML NewReleaseMessage ainsi que l’audio, les pochettes et les vidéos qu’ils référencent.

Scopes

Scope Autorise
ddex:validate Les tests uniquement. Idéal pour la CI.
ddex:write Les tests, les livraisons, les envois directs et le statut des livraisons.

1. Tester d’abord

POST /ddex/validate exécute toutes les vérifications d’une livraison : le XML, les règles HILLS, les fichiers audio, pochettes et vidéos, les UPC et ISRC comparés à votre catalogue, les genres, les territoires et les accords. Rien n’est créé : ni sortie, ni enregistrement, ni artiste, ni code, ni livraison. Envoyez un .zip ou un seul .xml.

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
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 désigne l’artiste ou le label auquel le lot est destiné. Omettez-le pour votre propre catalogue. Pour un fichier XML, envoyez Content-Type: application/xml. Vous pouvez aussi envoyer du multipart/form-data avec le champ file (jusqu’à 512 Mo).

La réponse contient la version ERN, un résumé, chaque vérification par étape (pass, warning, error, skipped) et un verdict :

Verdict Signification
would_import Aucun problème. La sortie deviendrait un brouillon.
would_import_with_warnings La sortie serait importée. Lisez les avertissements.
would_be_flagged La sortie attendrait l’équipe HILLS : un retrait, ou une mise à jour d’une sortie en vérification ou en ligne.
would_be_rejected La sortie comporte des erreurs. Rien ne serait créé pour elle.

Un lot qui comporte des erreurs renvoie quand même 200 : c’est le verdict qui indique le problème. Un lot trop volumineux pour être testé renvoie 413 too_large, et un trop grand nombre de tests simultanés peut renvoyer 429 busy. Chaque test est aussi listé sur la page DDEX de l’application web, sous Test reports, pendant 90 jours.

2. Livrer

POST /ddex accepte le zip en corps brut (Content-Type: application/zip, jusqu’à 20 Go) ou dans le champ multipart file (jusqu’à 512 Mo). Il renvoie immédiatement 202 :

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"}}

Pour les gros fichiers, préférez l’envoi direct.

Envoi direct pour les lots volumineux

Avec l’envoi direct, le fichier va directement dans le stockage au lieu de transiter par l’API.

  1. Démarrer. POST /ddex/uploads avec name et size en octets (jusqu’à 20 Go), et member_id si nécessaire.
  2. Envoyer. Jusqu’à 64 Mo, vous recevez une seule upload.url : envoyez-y le fichier entier en PUT. Au-delà de 64 Mo, vous recevez upload.part_size et une URL par partie. Envoyez en PUT chaque tranche de part_size octets vers son URL (la dernière tranche est plus courte). Les parties peuvent arriver dans n’importe quel ordre, et en parallèle. Ces URL sont signées : n’y envoyez aucun en-tête Authorization.
  3. Finaliser. POST /ddex/uploads/{id}/commit. L’appel vérifie que chaque partie est arrivée avec la bonne taille, puis met le lot en file d’attente comme POST /ddex (202).
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

Les URL des parties sont valables 6 heures. GET /ddex/uploads/{id} fournit de nouvelles URL pour les parties encore manquantes, avec received_parts et parts_total. Une finalisation alors que des parties manquent renvoie 409 upload_incomplete et liste missing et wrong_size : envoyez ces parties, puis finalisez à nouveau. DELETE /ddex/uploads/{id} abandonne un envoi que vous ne terminerez pas. Les envois non finalisés sont supprimés au bout de 7 jours.

Par SFTP

Chaque boîte de dépôt DDEX correspond à un identifiant SFTP avec deux dossiers. Vous recevez l’identifiant avec votre boîte de dépôt, sur la page DDEX de l’application web.

Dossier Ce qui se passe
/production/<batch>/ Livraison. Dès l’arrivée du marqueur, le lot est importé.
/test/<batch>/ Test, comme avec POST /ddex/validate. Rien n’est créé. Le rapport est écrit à côté : /test/<batch>.report.txt et .report.json.

Déposez le XML et ses fichiers dans le dossier du lot, puis le marqueur en dernier : BatchComplete_*.xml, ou n’importe quel fichier *.complete. Un fichier /test/<file>.xml ou .zip seul est également testé. Tout autre fichier déposé dans /test, comme ping.txt, sert de test de connexion. Un dossier de lot de production qui ne reçoit jamais son marqueur est supprimé au bout de 7 jours. Tout ce qui se trouve dans /test est supprimé après le même délai. Voir Dossier de test.

3. Lire le rapport de livraison

Interrogez GET /ddex/{id} toutes les 10 à 30 secondes, ou abonnez-vous au webhook ddex.import.imported. Le statut passe par queued → parsing → validating → importing, puis se termine par :

  • done : toutes les sorties ont été importées ;
  • partial : certaines sorties ont été écartées ;
  • failed : rien n’a été importé.
curl "https://api.hillsmusic.com/v1/ddex/311" \
  -H "Authorization: Bearer $HILLS_API_KEY"

La réponse contient des compteurs et un élément par sortie, chacun avec son outcome, son release_id et ses errors (chaque erreur indique son champ DDEX). GET /ddex liste vos 100 dernières livraisons.

Ce qui est créé ou signalé

Résultat Quand
created Une nouvelle sortie. Elle devient un brouillon dans le catalogue de member_id.
updated L’UPC correspond déjà à un brouillon (ou à une sortie renvoyée pour modifications) dans ce catalogue. Ce brouillon est mis à jour.
flagged Un retrait, ou une mise à jour d’une sortie en vérification ou en ligne. Elle n’est pas appliquée : l’équipe HILLS l’examine.
left_out La sortie comportait des erreurs. Rien n’a été créé pour elle. Corrigez-la et livrez-la à nouveau.
test Un message marqué TestMessage : vérifié, rien n’est créé.

Un ISRC que vous possédez déjà réutilise l’enregistrement correspondant. Un ISRC qui appartient à un autre compte entraîne l’exclusion de la sortie. Les brouillons passent ensuite par la vérification comme d’habitude : soumettez-les dans l’application web, ou demandez à HILLS Music d’activer la soumission automatique pour votre boîte de dépôt. Suivez-les avec GET /releases et des webhooks comme release.approved et release.live.

Tous les paramètres figurent dans la référence Livraisons DDEX.

Prêt à vous intégrer ?

Demandez l’accès à l’API : nous vous répondons sous 1–3 business days.