Pular para o conteúdo
HILLS API v1 Acesso antecipado

Guias

Entrega DDEX

Envie lançamentos em DDEX ERN: teste um lote com POST /ddex/validate, entregue com POST /ddex ou uploads diretos, use SFTP e leia o relatório de entrega.

Atualizado em

Os lançamentos entram na HILLS Music em lotes DDEX ERN. A API não cria nem edita lançamentos avulsos campo a campo. Você envia o mesmo lote que enviaria a uma plataforma, pela API ou por SFTP. Cada lançamento do lote vira um rascunho no seu catálogo e passa pela revisão e pela entrega às plataformas como de costume.

Versões do ERN

Versão Status
ERN 4.3 (http://ddex.net/xml/ern/43) Recomendada
4.2, 4.1 Aceitas
3.8.2, 3.8.1, 3.8, 3.7 Aceitas. O relatório avisa que a versão é legada.
Qualquer outra Rejeitada

Todas as versões aceitas passam pelas mesmas verificações e pela mesma importação. Um lote é um zip com um ou mais arquivos XML NewReleaseMessage e o áudio, as capas e os vídeos a que eles se referem.

Escopos

Escopo Permite
ddex:validate Apenas testes. Bom para CI.
ddex:write Testes, entregas, uploads diretos e status das entregas.

1. Teste primeiro

POST /ddex/validate executa todas as verificações de uma entrega: o XML, as regras da HILLS, os arquivos de áudio, capa e vídeo, os UPCs e ISRCs em relação ao seu catálogo, gêneros, territórios e contratos (deals). Nada é criado: nenhum lançamento, gravação, artista, código ou entrega. Envie um .zip ou um único .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 é o artista ou gravadora a que o lote se destina. Omita-o para o seu próprio catálogo. Para um arquivo XML, envie Content-Type: application/xml. Você também pode enviar multipart/form-data com o campo file (até 512 MB).

A resposta traz a versão do ERN, um resumo, cada verificação por etapa (pass, warning, error, skipped) e um veredito:

Veredito Significa
would_import Sem problemas. Viraria um rascunho.
would_import_with_warnings Seria importado. Leia os avisos.
would_be_flagged Aguardaria a equipe da HILLS: uma remoção, ou uma atualização de um lançamento em revisão ou no ar.
would_be_rejected Tem erros. Nada seria criado para esse lançamento.

Um lote com erros também responde 200. O veredito diz o que deu errado. Um lote grande demais para teste responde 413 too_large, e muitos testes ao mesmo tempo podem responder 429 busy. Todo teste também aparece na página DDEX do app web, em Test reports, por 90 dias.

2. Entregue

POST /ddex recebe o zip como corpo bruto (Content-Type: application/zip, até 20 GB) ou no campo multipart file (até 512 MB). Ele responde 202 na hora:

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

Para arquivos grandes, prefira um upload direto.

Uploads diretos para lotes grandes

Um upload direto envia o arquivo direto para o armazenamento, sem passar pela API.

  1. Inicie. POST /ddex/uploads com name e size em bytes (até 20 GB), e member_id se necessário.
  2. Envie. Até 64 MB, você recebe uma única upload.url: faça PUT do arquivo inteiro nela. Acima de 64 MB, você recebe upload.part_size e uma URL por parte. Faça PUT de cada fatia de part_size bytes na URL correspondente (a última fatia é menor). As partes podem ir em qualquer ordem, e em paralelo. Essas URLs são assinadas: não envie o header Authorization para elas.
  3. Confirme. POST /ddex/uploads/{id}/commit. Ele verifica se todas as partes chegaram com o tamanho certo e então coloca o lote na fila como 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

As URLs das partes valem por 6 horas. GET /ddex/uploads/{id} gera URLs novas para as partes que ainda faltam, com received_parts e parts_total. Uma confirmação com partes faltando responde 409 upload_incomplete e lista missing e wrong_size: envie essas partes e confirme de novo. DELETE /ddex/uploads/{id} descarta um upload que você não vai concluir. Uploads não confirmados são removidos após 7 dias.

Via SFTP

Cada caixa de entrada DDEX é um login SFTP com duas pastas. Você recebe o login junto com a caixa de entrada, na página DDEX do app web.

Pasta O que acontece
/production/<batch>/ Entregue. Quando o marcador chega, o lote é importado.
/test/<batch>/ Testado, como em POST /ddex/validate. Nada é criado. O relatório é gravado ao lado: /test/<batch>.report.txt e .report.json.

Envie o XML e os arquivos dele para a pasta do lote e, por último, o marcador: BatchComplete_*.xml, ou qualquer arquivo *.complete. Um /test/<file>.xml ou .zip avulso também é testado. Qualquer outro arquivo em /test, como ping.txt, é um teste de conexão. Uma pasta de lote de produção que nunca recebe o marcador é removida após 7 dias. Tudo o que estiver em /test sai após o mesmo prazo. Veja Pasta de teste.

3. Leia o relatório de entrega

Consulte GET /ddex/{id} a cada 10 a 30 segundos, ou assine o webhook ddex.import.imported. O status passa por queued → parsing → validating → importing e termina como:

  • done: todos os lançamentos entraram;
  • partial: alguns lançamentos ficaram de fora;
  • failed: nada foi importado.
curl "https://api.hillsmusic.com/v1/ddex/311" \
  -H "Authorization: Bearer $HILLS_API_KEY"

A resposta traz contagens e um item por lançamento, cada um com outcome, release_id e errors (cada erro indica o seu campo DDEX). GET /ddex lista as suas últimas 100 entregas.

O que é criado ou sinalizado

Resultado Quando
created Um lançamento novo. Ele vira um rascunho no catálogo de member_id.
updated O UPC já é um rascunho ali (ou um lançamento devolvido para alterações). Esse rascunho é atualizado.
flagged Uma remoção, ou uma atualização de um lançamento em revisão ou no ar. Não é aplicada. A equipe da HILLS analisa.
left_out O lançamento tinha erros. Nada foi criado para ele. Corrija e entregue de novo.
test Uma mensagem marcada como TestMessage: verificada, nada criado.

Um ISRC que você já tem reaproveita a gravação correspondente. Um ISRC que pertence a outra conta deixa o lançamento de fora. Os rascunhos então passam pela revisão como de costume: envie-os pelo app web, ou peça à HILLS Music para ativar o envio automático na sua caixa de entrada. Acompanhe-os com GET /releases e com webhooks como release.approved e release.live.

Os parâmetros completos estão na referência de Entregas DDEX.

Pronto para integrar?

Solicite acesso à API e retornamos em 1 a 3 dias úteis.