Entregas DDEX
Entrega lotes DDEX ERN (se recomienda 4.3) a producción, pruébalos antes (sin crear nada), usa subidas directas para los grandes y consulta su estado.
Entrega lotes DDEX ERN (se recomienda 4.3) a producción, pruébalos antes (sin crear nada), usa subidas directas para los grandes y consulta su estado.
URL base https://api.hillsmusic.com/v1. Cada solicitud envía una clave de API: Authorization: Bearer hm_live_….
- Probar un mensaje o lote DDEX
- Entregar un lote DDEX (se recomienda ERN 4.3)
- Listar entregas
- Iniciar una subida directa (lotes grandes)
- Estado de una subida directa
- Descartar una subida directa
- Confirmar una subida directa
- Estado de la entrega
Probar un mensaje o lote DDEX
POST /v1/ddex/validate · Ámbito: ddex:validate o ddex:write
La vía de pruebas: un .xml (Content-Type: application/xml) o un .zip, que se comprueba como una entrega (el XML, las reglas de HILLS, los archivos de audio, portada y video, los UPC e ISRC frente al catálogo). No se crea nada: ni lanzamientos, ni grabaciones, ni artistas, ni códigos, ni entregas. La prueba aparece en la página DDEX del panel (Test reports). Devuelve cada comprobación por fase (pass / warning / error / skipped), lo que HILLS crearía y el veredicto: would_import, would_import_with_warnings, would_be_flagged o would_be_rejected. También funciona con ddex:write.
Parámetros
| Parámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
member_id |
query | integer | No | El artista o sello al que corresponde (tu propia cuenta si se omite). |
name |
query | string | No | Nombre de archivo para un cuerpo en bruto (predeterminado: batch.zip, o message.xml para XML). |
Cuerpo de la solicitud
El lote: el zip que entregas a las plataformas (XML del ERN + los recursos a los que remite) como cuerpo en bruto, un .xml suelto o el campo multipart file (con member_id como campo). Tipos de contenido: application/zip, application/xml, multipart/form-data.
Ejemplo de solicitud
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
Respuesta 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"
}
]
}
}
Errores
| Estado | Cuándo |
|---|---|
| 400 | invalid: un parámetro es incorrecto; field indica cuál. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 413 | too_large: supera el tamaño que admite una prueba; entrégalo con POST /ddex. |
| 429 | busy: demasiadas pruebas a la vez; vuelve a intentarlo en breve. rate_limited: espera los segundos que indique Retry-After. |
Entregar un lote DDEX (se recomienda ERN 4.3)
POST /v1/ddex · Ámbito: ddex:write
Envía el zip que entregas a las plataformas: uno o varios XML NewReleaseMessage del ERN con el audio, la portada y los videos a los que remiten. Como cuerpo en bruto (Content-Type: application/zip, hasta 20 GB) o en el campo multipart file (hasta 512 MB). Cada lanzamiento se convierte en un borrador en member_id (tu propio catálogo si se omite); un UPC que ya existe actualiza su borrador; las retiradas y las actualizaciones de lanzamientos publicados esperan al equipo de HILLS. Se recomienda ERN 4.3 (espacio de nombres http://ddex.net/xml/ern/43); 4.2, 4.1, 3.8.x (3.8.2, 3.8.1, 3.8) y 3.7 se aceptan y se leen de la misma forma (el informe advierte de que la versión es antigua); las demás versiones se rechazan. 202 con el id de la entrega: consulta GET /ddex/{id}.
Parámetros
| Parámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
member_id |
query | integer | No | El artista o sello al que corresponde (tu propia cuenta si se omite). |
name |
query | string | No | Nombre de archivo para un cuerpo en bruto (predeterminado: batch.zip). |
Cuerpo de la solicitud
El lote: el zip que entregas a las plataformas (XML del ERN + los recursos a los que remite) como cuerpo en bruto, un .xml suelto o el campo multipart file (con member_id como campo). Tipos de contenido: application/zip, application/xml, multipart/form-data.
Ejemplo de solicitud
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
Respuesta 202
{
"data": {
"id": 311,
"status": "queued",
"environment": "production",
"status_url": "/v1/ddex/311"
}
}
Errores
| Estado | Cuándo |
|---|---|
| 400 | invalid: un parámetro es incorrecto; field indica cuál. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 413 | too_large: más de 20 GB (cuerpo en bruto) o de 512 MB (multipart). |
| 429 | rate_limited: espera los segundos que indique Retry-After. |
Listar entregas
GET /v1/ddex · Ámbito: ddex:write o ddex:validate
Tus últimas 100 entregas DDEX, de la más reciente a la más antigua (no incluye las subidas aún sin confirmar).
Ejemplo de solicitud
curl "https://api.hillsmusic.com/v1/ddex" \
-H "Authorization: Bearer $HILLS_API_KEY"
Respuesta 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"
}
]
}
Errores
| Estado | Cuándo |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 429 | rate_limited: espera los segundos que indique Retry-After. |
Iniciar una subida directa (lotes grandes)
POST /v1/ddex/uploads · Ámbito: ddex:write
Recomendado para zips grandes: el archivo va directamente al almacenamiento en lugar de pasar por la API. Envía el nombre del archivo y su tamaño en bytes (hasta 20 GB). Hasta 64 MB recibes una sola URL a la que enviar el archivo completo con PUT; por encima, un tamaño de parte y una URL por parte: envía con PUT cada fragmento de part_size bytes (el último, más corto) a su URL, en cualquier orden y en paralelo. Las URL funcionan durante 6 horas; GET /ddex/uploads/{id} da URL nuevas para las partes que aún faltan. Después, POST /ddex/uploads/{id}/commit. DELETE /ddex/uploads/{id} descarta una subida que no vayas a terminar; las subidas sin confirmar se eliminan a los 7 días.
Cuerpo de la solicitud
JSON.
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
name |
string | Sí | El nombre del archivo (.zip o .xml). |
size |
integer | Sí | El tamaño del archivo en bytes. |
member_id |
integer | No | El artista o sello al que corresponde (tu propia cuenta si se omite). |
Ejemplo de solicitud
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}'
Respuesta 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"
}
}
Errores
| Estado | Cuándo |
|---|---|
| 400 | invalid: un parámetro es incorrecto; field indica cuál. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 429 | rate_limited: espera los segundos que indique Retry-After. |
Estado de una subida directa
GET /v1/ddex/uploads/{id} · Ámbito: ddex:write
Si la subida aún no está confirmada: URL nuevas para las partes que faltan (las primeras caducan a las 6 horas), received_parts y parts_total. Una vez confirmada: el id de su entrega y status_url.
Parámetros
| Parámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id |
path | integer | Sí | El id de la subida. |
Ejemplo de solicitud
curl "https://api.hillsmusic.com/v1/ddex/uploads/312" \
-H "Authorization: Bearer $HILLS_API_KEY"
Respuesta 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
}
}
Errores
| Estado | Cuándo |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 404 | not_found: no existe o no es tuyo. |
| 429 | rate_limited: espera los segundos que indique Retry-After. |
Descartar una subida directa
DELETE /v1/ddex/uploads/{id} · Ámbito: ddex:write
Descarta una subida que no vas a terminar, junto con las partes ya enviadas. 409 si ya se confirmó.
Parámetros
| Parámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id |
path | integer | Sí | El id de la subida. |
Ejemplo de solicitud
curl -X DELETE "https://api.hillsmusic.com/v1/ddex/uploads/312" \
-H "Authorization: Bearer $HILLS_API_KEY"
Respuesta 200
{
"data": {
"id": 312,
"deleted": true
}
}
Errores
| Estado | Cuándo |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 404 | not_found: no existe o no es tuyo. |
| 409 | already_committed: ya está confirmada y no se puede descartar. |
| 429 | rate_limited: espera los segundos que indique Retry-After. |
Confirmar una subida directa
POST /v1/ddex/uploads/{id}/commit · Ámbito: ddex:write
Comprueba que todas las partes llegaron con el tamaño correcto y pone el lote en cola exactamente igual que POST /ddex. 409 upload_incomplete enumera las partes que faltan o cuyo tamaño es incorrecto (súbelas y vuelve a confirmar). 202 con el id de la entrega; consulta GET /ddex/{id}.
Parámetros
| Parámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id |
path | integer | Sí | El id de la subida. |
Ejemplo de solicitud
curl -X POST "https://api.hillsmusic.com/v1/ddex/uploads/312/commit" \
-H "Authorization: Bearer $HILLS_API_KEY"
Respuesta 202
{
"data": {
"id": 312,
"status": "queued",
"environment": "production",
"status_url": "/v1/ddex/312"
}
}
Errores
| Estado | Cuándo |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 404 | not_found: no existe o no es tuyo. |
| 409 | upload_incomplete: faltan partes o su tamaño es incorrecto (missing y wrong_size las enumeran). already_committed: ya se confirmó (status_url apunta a la entrega). commit_in_progress: hay otra confirmación de esta subida en curso. |
| 429 | rate_limited: espera los segundos que indique Retry-After. |
Estado de la entrega
GET /v1/ddex/{id} · Ámbito: ddex:write o ddex:validate
queued → parsing → validating → importing → done / partial / failed, con un elemento por lanzamiento (creado, actualizado, marcado para el equipo de HILLS, excluido, prueba) y cada error con su campo DDEX. GET /ddex enumera tus últimas 100.
Parámetros
| Parámetro | Ubicación | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
id |
path | integer | Sí | El id de la entrega (de POST /ddex o de la confirmación). |
Ejemplo de solicitud
curl "https://api.hillsmusic.com/v1/ddex/311" \
-H "Authorization: Bearer $HILLS_API_KEY"
Respuesta 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": []
}
]
}
}
Errores
| Estado | Cuándo |
|---|---|
| 401 | unauthenticated, invalid_key, key_revoked, key_expired o test_keys_retired. |
| 403 | insufficient_scope: a la clave le falta el ámbito; scope indica cuál. account_inactive o api_not_in_plan. |
| 404 | not_found: no existe o no es tuyo. |
| 429 | rate_limited: espera los segundos que indique Retry-After. |