# Webhooks > Avisos de HILLS Music a tus endpoints: lanzamientos, entregas, DDEX, liquidaciones, pagos, solicitudes y soporte en vivo. Firmados y con reintentos. Avisos de HILLS Music a tus endpoints: lanzamientos, entregas, DDEX, liquidaciones, pagos, solicitudes y soporte en vivo. Firmados y con reintentos. URL base `https://api.hillsmusic.com/v1`. Cada solicitud envía una clave de API: `Authorization: Bearer hm_live_…`. - Listar los tipos de evento de webhook - Listar los endpoints de webhook - Crear un endpoint de webhook - Obtener un endpoint de webhook - Actualizar un endpoint de webhook - Eliminar un endpoint de webhook - Renovar el secreto de un webhook - Enviar un evento de prueba - Listar las entregas de un endpoint - Reintentar una entrega ## Listar los tipos de evento de webhook `GET /v1/webhooks/events` · Ámbito: `webhooks:read` o `webhooks:write` Todos los tipos de evento a los que puede suscribirse un endpoint, con su significado. Los payloads se documentan en Webhooks, dentro de esta referencia. ### Ejemplo de solicitud ```bash curl "https://api.hillsmusic.com/v1/webhooks/events" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `200` ```json { "data": [ { "type": "release.approved", "label": "Release approved", "description": "A release was approved and is queued for its stores." } ] } ``` ### 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. | ## Listar los endpoints de webhook `GET /v1/webhooks` · Ámbito: `webhooks:read` o `webhooks:write` Tus endpoints de webhook (20 como máximo), del más antiguo al más reciente. El secreto nunca aparece en la lista. ### Ejemplo de solicitud ```bash curl "https://api.hillsmusic.com/v1/webhooks" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `200` ```json { "data": [ { "id": 7, "url": "https://example.com/hills/webhooks", "description": "Order system", "events": [ "release.approved", "delivery.store_status_changed" ], "enabled": true, "secret_prefix": "whsec_3f9a1c", "created_at": "2026-10-13T09:00:00Z", "updated_at": "2026-10-13T09:00:00Z", "last_success_at": null, "last_failure_at": null, "failure_count": 0, "disabled_at": null, "disabled_reason": null } ] } ``` ### 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. | ## Crear un endpoint de webhook `POST /v1/webhooks` · Ámbito: `webhooks:write` Registra una URL https para los eventos que elijas. La respuesta incluye el secreto de firma, una sola vez. La URL debe ser pública: se rechazan las direcciones privadas, locales y de metadatos. ### Cuerpo de la solicitud JSON. | Campo | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | | `url` | string | Sí | Adónde enviar los eventos por POST: una URL https:// pública en el puerto 443. | | `description` | string | No | Una nota para ti, por ejemplo, el sistema que los recibe. | | `events` | array | Sí | Los tipos de evento que se envían (consulta Webhooks en esta referencia). | | `enabled` | boolean | No | Valor predeterminado: true. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.hillsmusic.com/v1/webhooks" \ -H "Authorization: Bearer $HILLS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com/hills/webhooks","description":"Order system","events":["release.approved","delivery.store_status_changed"]}' ``` ### Respuesta `201` ```json { "endpoint": { "id": 7, "url": "https://example.com/hills/webhooks", "description": "Order system", "events": [ "release.approved", "delivery.store_status_changed" ], "enabled": true, "secret_prefix": "whsec_3f9a1c", "created_at": "2026-10-13T09:00:00Z", "updated_at": "2026-10-13T09:00:00Z", "last_success_at": null, "last_failure_at": null, "failure_count": 0, "disabled_at": null, "disabled_reason": null }, "secret": "whsec_3f9a1c0d5e7b2a4c6e8f0a1b3c5d7e9f1a2b3c4d5e6f7a8b" } ``` ### Errores | Estado | Cuándo | | --- | --- | | 400 | invalid: un parámetro es incorrecto; field indica cuál. invalid_url: no es una URL https pública en el puerto 443. | | 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. | | 409 | too_many: ya hay 20 endpoints. | | 429 | rate_limited: espera los segundos que indique Retry-After. | ## Obtener un endpoint de webhook `GET /v1/webhooks/{id}` · Ámbito: `webhooks:read` o `webhooks:write` Un endpoint con su estado de salud: último éxito y último fallo, intentos fallidos consecutivos y por qué está desactivado. ### Parámetros | Parámetro | Ubicación | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | --- | | `id` | path | integer | Sí | El id del endpoint. | ### Ejemplo de solicitud ```bash curl "https://api.hillsmusic.com/v1/webhooks/7" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `200` ```json { "data": { "id": 7, "url": "https://example.com/hills/webhooks", "description": "Order system", "events": [ "release.approved", "delivery.store_status_changed" ], "enabled": true, "secret_prefix": "whsec_3f9a1c", "created_at": "2026-10-13T09:00:00Z", "updated_at": "2026-10-13T09:00:00Z", "last_success_at": null, "last_failure_at": null, "failure_count": 0, "disabled_at": null, "disabled_reason": null } } ``` ### 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. | ## Actualizar un endpoint de webhook `PATCH /v1/webhooks/{id}` · Ámbito: `webhooks:write` Cambia su URL, su descripción o sus eventos, o lo desactiva y lo reactiva (enabled). Al reactivarlo se pone a cero su contador de fallos; las entregas abandonadas mientras estaba desactivado pueden volver a enviarse con retry. ### Parámetros | Parámetro | Ubicación | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | --- | | `id` | path | integer | Sí | El id del endpoint. | ### Cuerpo de la solicitud JSON. | Campo | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | | `url` | string | No | Adónde enviar los eventos por POST: una URL https:// pública en el puerto 443. | | `description` | string | No | Una nota para ti, por ejemplo, el sistema que los recibe. | | `events` | array | No | Los tipos de evento que se envían (consulta Webhooks en esta referencia). | | `enabled` | boolean | No | false lo desactiva; true lo reactiva. | ### Ejemplo de solicitud ```bash curl -X PATCH "https://api.hillsmusic.com/v1/webhooks/7" \ -H "Authorization: Bearer $HILLS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"enabled":true}' ``` ### Respuesta `200` ```json { "data": { "id": 7, "url": "https://example.com/hills/webhooks", "description": "Order system", "events": [ "release.approved", "delivery.store_status_changed" ], "enabled": true, "secret_prefix": "whsec_3f9a1c", "created_at": "2026-10-13T09:00:00Z", "updated_at": "2026-10-13T09:00:00Z", "last_success_at": null, "last_failure_at": null, "failure_count": 0, "disabled_at": null, "disabled_reason": null } } ``` ### Errores | Estado | Cuándo | | --- | --- | | 400 | invalid: un parámetro es incorrecto; field indica cuál. invalid_url: no es una URL https pública en el puerto 443. | | 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. | ## Eliminar un endpoint de webhook `DELETE /v1/webhooks/{id}` · Ámbito: `webhooks:write` Elimina el endpoint y su registro de entregas. No se le envía nada más. ### Parámetros | Parámetro | Ubicación | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | --- | | `id` | path | integer | Sí | El id del endpoint. | ### Ejemplo de solicitud ```bash curl -X DELETE "https://api.hillsmusic.com/v1/webhooks/7" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `200` ```json { "ok": 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. | | 429 | rate_limited: espera los segundos que indique Retry-After. | ## Renovar el secreto de un webhook `POST /v1/webhooks/{id}/roll-secret` · Ámbito: `webhooks:write` Genera un nuevo secreto de firma; el anterior deja de funcionar al instante. El nuevo secreto solo aparece en esta respuesta. ### Parámetros | Parámetro | Ubicación | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | --- | | `id` | path | integer | Sí | El id del endpoint. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/roll-secret" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `200` ```json { "endpoint": { "id": 7, "url": "https://example.com/hills/webhooks", "description": "Order system", "events": [ "release.approved", "delivery.store_status_changed" ], "enabled": true, "secret_prefix": "whsec_3f9a1c", "created_at": "2026-10-13T09:00:00Z", "updated_at": "2026-10-13T09:00:00Z", "last_success_at": null, "last_failure_at": null, "failure_count": 0, "disabled_at": null, "disabled_reason": null }, "secret": "whsec_3f9a1c0d5e7b2a4c6e8f0a1b3c5d7e9f1a2b3c4d5e6f7a8b" } ``` ### 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. | ## Enviar un evento de prueba `POST /v1/webhooks/{id}/test` · Ámbito: `webhooks:write` Pone en cola un evento webhook.test para este endpoint, tenga los eventos que tenga, firmado como cualquier otro. Su resultado aparece en las entregas. ### Parámetros | Parámetro | Ubicación | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | --- | | `id` | path | integer | Sí | El id del endpoint. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/test" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `202` ```json { "delivery": { "id": 1042, "endpoint_id": 7, "event": "webhook.test", "event_id": "5d0c2b7e-8a43-4c4e-9f1e-2f0b9a6c1d33", "attempt": 0, "status": "pending", "response_status": null, "response_ms": null, "next_attempt_at": "2026-10-13T09:05:00Z", "error": null, "created_at": "2026-10-13T09:05:00Z", "delivered_at": null, "payload": { "id": "5d0c2b7e-8a43-4c4e-9f1e-2f0b9a6c1d33", "type": "release.approved", "api_version": "v1", "occurred_at": "2026-10-13T09:05:00Z", "account_id": 12, "data": { "release": { "id": 812, "title": "Midnight Run" } } } } } ``` ### 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 | endpoint_disabled: el endpoint está desactivado. | | 429 | rate_limited: espera los segundos que indique Retry-After. | ## Listar las entregas de un endpoint `GET /v1/webhooks/{id}/deliveries` · Ámbito: `webhooks:read` o `webhooks:write` Lo que se envió al endpoint en los últimos 30 días, de lo más reciente a lo más antiguo: el payload, los intentos, el último estado HTTP con su hora y el error. ### Parámetros | Parámetro | Ubicación | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | --- | | `id` | path | integer | Sí | El id del endpoint. | | `status` | query | `pending` \| `succeeded` \| `failed` | No | Solo estas. | | `event` | query | string | No | Solo este tipo de evento. | | `limit` | query | number | No | 1–100; predeterminado: 50. | | `before` | query | number | No | Entregas anteriores a este id de entrega (la página siguiente). | ### Ejemplo de solicitud ```bash curl "https://api.hillsmusic.com/v1/webhooks/7/deliveries?status=failed" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `200` ```json { "data": [ { "id": 1042, "endpoint_id": 7, "event": "release.approved", "event_id": "5d0c2b7e-8a43-4c4e-9f1e-2f0b9a6c1d33", "attempt": 1, "status": "succeeded", "response_status": 200, "response_ms": 184, "next_attempt_at": "2026-10-13T09:05:00Z", "error": null, "created_at": "2026-10-13T09:05:00Z", "delivered_at": "2026-10-13T09:05:01Z", "payload": { "id": "5d0c2b7e-8a43-4c4e-9f1e-2f0b9a6c1d33", "type": "release.approved", "api_version": "v1", "occurred_at": "2026-10-13T09:05:00Z", "account_id": 12, "data": { "release": { "id": 812, "title": "Midnight Run" } } } } ], "has_more": false } ``` ### 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. | | 404 | not_found: no existe o no es tuyo. | | 429 | rate_limited: espera los segundos que indique Retry-After. | ## Reintentar una entrega `POST /v1/webhooks/{id}/deliveries/{delivery_id}/retry` · Ámbito: `webhooks:write` Vuelve a enviar ahora el mismo evento (mismo id y mismo payload) al endpoint. ### Parámetros | Parámetro | Ubicación | Tipo | Obligatorio | Descripción | | --- | --- | --- | --- | --- | | `id` | path | integer | Sí | El id del endpoint. | | `delivery_id` | path | integer | Sí | El id de la entrega. | ### Ejemplo de solicitud ```bash curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/deliveries/1042/retry" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Respuesta `202` ```json { "delivery": { "id": 1042, "endpoint_id": 7, "event": "release.approved", "event_id": "5d0c2b7e-8a43-4c4e-9f1e-2f0b9a6c1d33", "attempt": 1, "status": "pending", "response_status": 200, "response_ms": 184, "next_attempt_at": "2026-10-13T09:05:00Z", "error": null, "created_at": "2026-10-13T09:05:00Z", "delivered_at": "2026-10-13T09:05:01Z", "payload": { "id": "5d0c2b7e-8a43-4c4e-9f1e-2f0b9a6c1d33", "type": "release.approved", "api_version": "v1", "occurred_at": "2026-10-13T09:05:00Z", "account_id": 12, "data": { "release": { "id": 812, "title": "Midnight Run" } } } } } ``` ### 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 | endpoint_disabled: el endpoint está desactivado. | | 429 | rate_limited: espera los segundos que indique Retry-After. | Fuente: https://developer.hillsmusic.com/es/reference/webhooks/