Entregas DDEX
Entregue lotes DDEX ERN (4.3 recomendado) em produção, teste-os antes (nada é criado), use uploads diretos para os grandes e acompanhe o status.
Entregue lotes DDEX ERN (4.3 recomendado) em produção, teste-os antes (nada é criado), use uploads diretos para os grandes e acompanhe o status.
URL base https://api.hillsmusic.com/v1. Toda requisição envia uma chave de API: Authorization: Bearer hm_live_….
- Testar uma mensagem ou um lote DDEX
- Entregar um lote DDEX (ERN 4.3 recomendado)
- Listar entregas
- Iniciar um upload direto (lotes grandes)
- Situação de um upload direto
- Descartar um upload direto
- Confirmar um upload direto
- Status da entrega
Testar uma mensagem ou um lote DDEX
POST /v1/ddex/validate · Escopo: ddex:validate ou ddex:write
O caminho de teste: um .xml (Content-Type: application/xml) ou um .zip, verificado como uma entrega (o XML, as regras da HILLS, os arquivos de áudio, capa e vídeo, os UPCs e ISRCs em relação ao catálogo). Nada é criado: nenhum lançamento, gravação, artista, código ou entrega. O teste aparece na página DDEX do painel (Test reports). Cada verificação por etapa (pass / warning / error / skipped), o que a HILLS criaria e o veredito: would_import, would_import_with_warnings, would_be_flagged ou would_be_rejected. ddex:write também funciona.
Parâmetros
| Parâmetro | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
member_id |
query | integer | Não | O artista ou gravadora a que se destina (você mesmo, se omitido). |
name |
query | string | Não | Nome do arquivo para um corpo bruto (padrão batch.zip, ou message.xml para XML). |
Corpo da requisição
O lote: o zip que você entrega às plataformas (XML ERN + os recursos a que ele se refere) como corpo bruto, um .xml avulso, ou o campo multipart file (com member_id como campo). Content types: application/zip, application/xml, multipart/form-data.
Exemplo de requisição
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.zip
Resposta 200
{
"data": {
"ern_version": "4.3",
"verdict": "would_be_rejected",
"summary": {
"messages": 1,
"releases": 1,
"pass": 41,
"warnings": 1,
"errors": 2,
"skipped": 1
},
"checks": [
{
"stage": "release",
"label": "Label",
"status": "error",
"message": "ReleaseLabelReference is required…",
"field": "Release/ReleaseLabelReference"
}
]
}
}
Erros
| Status | Quando |
|---|---|
| 400 | invalid: um parâmetro está errado; field indica qual. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 413 | too_large: maior do que um teste aceita; entregue-o com POST /ddex. |
| 429 | busy: testes demais ao mesmo tempo; tente de novo em instantes. rate_limited: aguarde Retry-After segundos. |
Entregar um lote DDEX (ERN 4.3 recomendado)
POST /v1/ddex · Escopo: ddex:write
Envie o zip que você entrega às plataformas: XML(s) ERN NewReleaseMessage com o áudio, a capa e os vídeos a que se referem. Como corpo bruto (Content-Type: application/zip, até 20 GB) ou no campo multipart file (até 512 MB). Cada lançamento vira um rascunho em member_id (o seu próprio catálogo, se omitido); um UPC que já existe atualiza o rascunho dele; remoções e atualizações de lançamentos no ar aguardam a equipe. ERN 4.3 (namespace http://ddex.net/xml/ern/43) é o recomendado; 4.2, 4.1, 3.8.x (3.8.2, 3.8.1, 3.8) e 3.7 são aceitos e lidos da mesma forma (o relatório avisa que a versão é legada); outras versões são rejeitadas. 202 com o id da entrega — consulte GET /ddex/{id}.
Parâmetros
| Parâmetro | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
member_id |
query | integer | Não | O artista ou gravadora a que se destina (você mesmo, se omitido). |
name |
query | string | Não | Nome do arquivo para um corpo bruto (padrão batch.zip). |
Corpo da requisição
O lote: o zip que você entrega às plataformas (XML ERN + os recursos a que ele se refere) como corpo bruto, um .xml avulso, ou o campo multipart file (com member_id como campo). Content types: application/zip, application/xml, multipart/form-data.
Exemplo de requisição
curl -X POST "https://api.hillsmusic.com/v1/ddex?member_id=41" \
-H "Authorization: Bearer $HILLS_API_KEY" \
-H "Content-Type: application/zip" \
--data-binary @batch.zip
Resposta 202
{
"data": {
"id": 311,
"status": "queued",
"environment": "production",
"status_url": "/v1/ddex/311"
}
}
Erros
| Status | Quando |
|---|---|
| 400 | invalid: um parâmetro está errado; field indica qual. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 413 | too_large: acima de 20 GB (corpo bruto) ou 512 MB (multipart). |
| 429 | rate_limited: aguarde Retry-After segundos. |
Listar entregas
GET /v1/ddex · Escopo: ddex:write ou ddex:validate
Suas últimas 100 entregas DDEX, das mais recentes para as mais antigas (uploads ainda não confirmados ficam de fora).
Exemplo de requisição
curl "https://api.hillsmusic.com/v1/ddex" \
-H "Authorization: Bearer $HILLS_API_KEY"
Resposta 200
{
"data": [
{
"id": 311,
"member_id": 41,
"environment": "production",
"batch_name": "batch-0001.zip",
"status": "done",
"error": null,
"message_id": "MSG-2026-0001",
"ern_version": "4.3",
"message_count": 1,
"release_count": 1,
"track_count": 12,
"created_count": 1,
"updated_count": 0,
"flagged_count": 0,
"left_out_count": 0,
"release_ids": [
912
],
"created_at": "2026-10-07T09:00:00Z",
"started_at": "2026-10-07T09:00:02Z",
"finished_at": "2026-10-07T09:01:10Z"
}
]
}
Erros
| Status | Quando |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 429 | rate_limited: aguarde Retry-After segundos. |
Iniciar um upload direto (lotes grandes)
POST /v1/ddex/uploads · Escopo: ddex:write
Recomendado para zips grandes: o arquivo vai direto para o armazenamento, sem passar pela API. Envie o nome do arquivo e o tamanho em bytes (até 20 GB). Até 64 MB você recebe uma URL para fazer PUT do arquivo inteiro; acima disso, um tamanho de parte e uma URL por parte: faça PUT de cada fatia de part_size bytes (a última é menor) na URL correspondente, em qualquer ordem e em paralelo. As URLs valem por 6 horas; GET /ddex/uploads/{id} gera URLs novas para as partes que ainda faltam. Depois, POST /ddex/uploads/{id}/commit. DELETE /ddex/uploads/{id} descarta um upload que você não vai concluir; uploads não confirmados são removidos após 7 dias.
Corpo da requisição
JSON.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name |
string | Sim | O nome do arquivo (.zip ou .xml). |
size |
integer | Sim | O tamanho do arquivo em bytes. |
member_id |
integer | Não | O artista ou gravadora a que se destina (você mesmo, se omitido). |
Exemplo de requisição
curl -X POST "https://api.hillsmusic.com/v1/ddex/uploads" \
-H "Authorization: Bearer $HILLS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"batch-0001.zip","size":1073741824,"member_id":41}'
Resposta 201
{
"data": {
"id": 312,
"status": "uploading",
"environment": "production",
"name": "batch-0001.zip",
"size": 1073741824,
"expires_in": 21600,
"upload": {
"method": "multipart",
"url": null,
"part_size": 16777216,
"parts": [
{
"part_number": 1,
"url": "https://…"
}
]
},
"commit_url": "/v1/ddex/uploads/312/commit"
}
}
Erros
| Status | Quando |
|---|---|
| 400 | invalid: um parâmetro está errado; field indica qual. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 429 | rate_limited: aguarde Retry-After segundos. |
Situação de um upload direto
GET /v1/ddex/uploads/{id} · Escopo: ddex:write
Um upload ainda não confirmado: URLs novas para as partes que faltam (as primeiras expiram após 6 horas), received_parts e parts_total. Depois de confirmado: o id da entrega e status_url.
Parâmetros
| Parâmetro | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id |
path | integer | Sim | O id do upload. |
Exemplo de requisição
curl "https://api.hillsmusic.com/v1/ddex/uploads/312" \
-H "Authorization: Bearer $HILLS_API_KEY"
Resposta 200
{
"data": {
"id": 312,
"status": "uploading",
"environment": "production",
"name": "batch-0001.zip",
"size": 1073741824,
"expires_in": 21600,
"upload": {
"method": "multipart",
"url": null,
"part_size": 16777216,
"parts": [
{
"part_number": 7,
"url": "https://…"
}
]
},
"commit_url": "/v1/ddex/uploads/312/commit",
"received_parts": 63,
"parts_total": 64
}
}
Erros
| Status | Quando |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 404 | not_found: não existe, ou não é seu. |
| 429 | rate_limited: aguarde Retry-After segundos. |
Descartar um upload direto
DELETE /v1/ddex/uploads/{id} · Escopo: ddex:write
Descarta um upload que você não vai concluir, junto com as partes já enviadas. 409 depois de confirmado.
Parâmetros
| Parâmetro | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id |
path | integer | Sim | O id do upload. |
Exemplo de requisição
curl -X DELETE "https://api.hillsmusic.com/v1/ddex/uploads/312" \
-H "Authorization: Bearer $HILLS_API_KEY"
Resposta 200
{
"data": {
"id": 312,
"deleted": true
}
}
Erros
| Status | Quando |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 404 | not_found: não existe, ou não é seu. |
| 409 | already_committed: já confirmado; não pode ser descartado. |
| 429 | rate_limited: aguarde Retry-After segundos. |
Confirmar um upload direto
POST /v1/ddex/uploads/{id}/commit · Escopo: ddex:write
Verifica se todas as partes chegaram com o tamanho certo e coloca o lote na fila exatamente como POST /ddex. 409 upload_incomplete lista as partes ausentes e as de tamanho errado (envie-as e confirme de novo). 202 com o id da entrega; consulte GET /ddex/{id}.
Parâmetros
| Parâmetro | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id |
path | integer | Sim | O id do upload. |
Exemplo de requisição
curl -X POST "https://api.hillsmusic.com/v1/ddex/uploads/312/commit" \
-H "Authorization: Bearer $HILLS_API_KEY"
Resposta 202
{
"data": {
"id": 312,
"status": "queued",
"environment": "production",
"status_url": "/v1/ddex/312"
}
}
Erros
| Status | Quando |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 404 | not_found: não existe, ou não é seu. |
| 409 | upload_incomplete: partes ausentes ou com tamanho errado (missing e wrong_size as listam). already_committed: confirmado antes (status_url aponta para a entrega). commit_in_progress: outra confirmação deste upload está em andamento. |
| 429 | rate_limited: aguarde Retry-After segundos. |
Status da entrega
GET /v1/ddex/{id} · Escopo: ddex:write ou ddex:validate
queued → parsing → validating → importing → done / partial / failed, com um item por lançamento (criado, atualizado, sinalizado para a equipe, deixado de fora, teste) e cada erro com o seu campo DDEX. GET /ddex lista as suas últimas 100.
Parâmetros
| Parâmetro | Em | Tipo | Obrigatório | Descrição |
|---|---|---|---|---|
id |
path | integer | Sim | O id da entrega (de POST /ddex ou da confirmação). |
Exemplo de requisição
curl "https://api.hillsmusic.com/v1/ddex/311" \
-H "Authorization: Bearer $HILLS_API_KEY"
Resposta 200
{
"data": {
"id": 311,
"member_id": 41,
"environment": "production",
"status": "partial",
"message_id": "MSG-2026-0001",
"ern_version": "4.3",
"created_count": 1,
"left_out_count": 1,
"items": [
{
"ref": "R0",
"title": "Midnight Run",
"upc": "0602600000017",
"outcome": "created",
"release_id": 912,
"errors": []
}
]
}
}
Erros
| Status | Quando |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope: falta à chave o escopo; scope indica qual. account_inactive ou api_not_in_plan. |
| 404 | not_found: não existe, ou não é seu. |
| 429 | rate_limited: aguarde Retry-After segundos. |