# Webhooks > Endpoints HILLS Music calls when something happens: releases, store delivery, DDEX, statements, payouts, requests and Live support. Signed; retried. Endpoints HILLS Music calls when something happens: releases, store delivery, DDEX, statements, payouts, requests and Live support. Signed; retried. Base URL `https://api.hillsmusic.com/v1`. Every request sends an API key: `Authorization: Bearer hm_live_…`. - List webhook event types - List webhook endpoints - Create a webhook endpoint - Get a webhook endpoint - Update a webhook endpoint - Delete a webhook endpoint - Roll a webhook secret - Send a test event - List an endpoint's deliveries - Retry a delivery ## List webhook event types `GET /v1/webhooks/events` · Scope: `webhooks:read` or `webhooks:write` Every event type an endpoint can subscribe to, with what it means. Payloads are documented under webhooks in this reference. ### Example request ```bash curl "https://api.hillsmusic.com/v1/webhooks/events" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `200` ```json { "data": [ { "type": "release.approved", "label": "Release approved", "description": "A release was approved and is queued for its stores." } ] } ``` ### Errors | Status | When | | --- | --- | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 429 | rate_limited: wait Retry-After seconds. | ## List webhook endpoints `GET /v1/webhooks` · Scope: `webhooks:read` or `webhooks:write` Your webhook endpoints (at most 20), oldest first. The secret is never listed. ### Example request ```bash curl "https://api.hillsmusic.com/v1/webhooks" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `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 } ] } ``` ### Errors | Status | When | | --- | --- | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 429 | rate_limited: wait Retry-After seconds. | ## Create a webhook endpoint `POST /v1/webhooks` · Scope: `webhooks:write` Registers an https URL for the events you pick. The answer carries the signing secret, once. The URL must be public: private, local and metadata addresses are refused. ### Request body JSON. | Field | Type | Required | Description | | --- | --- | --- | --- | | `url` | string | Yes | Where to POST events: a public https:// URL on port 443. | | `description` | string | No | A note for you, e.g. the system that receives them. | | `events` | array | Yes | The event types to send (see Webhooks in this reference). | | `enabled` | boolean | No | Default true. | ### Example request ```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"]}' ``` ### Response `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" } ``` ### Errors | Status | When | | --- | --- | | 400 | invalid: a parameter is wrong; field names it. invalid_url: Not a public https URL on port 443. | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 409 | too_many: Already 20 endpoints. | | 429 | rate_limited: wait Retry-After seconds. | ## Get a webhook endpoint `GET /v1/webhooks/{id}` · Scope: `webhooks:read` or `webhooks:write` One endpoint with its health: last success and failure, failed attempts in a row, and why it is off. ### Parameters | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | path | integer | Yes | The endpoint id. | ### Example request ```bash curl "https://api.hillsmusic.com/v1/webhooks/7" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `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 } } ``` ### Errors | Status | When | | --- | --- | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 404 | not_found: no such thing, or not yours. | | 429 | rate_limited: wait Retry-After seconds. | ## Update a webhook endpoint `PATCH /v1/webhooks/{id}` · Scope: `webhooks:write` Changes its URL, description, events, or switches it off and on (enabled). Switching it on again clears its failure count; deliveries given up while it was off can be sent again with retry. ### Parameters | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | path | integer | Yes | The endpoint id. | ### Request body JSON. | Field | Type | Required | Description | | --- | --- | --- | --- | | `url` | string | No | Where to POST events: a public https:// URL on port 443. | | `description` | string | No | A note for you, e.g. the system that receives them. | | `events` | array | No | The event types to send (see Webhooks in this reference). | | `enabled` | boolean | No | false switches it off; true switches it back on. | ### Example request ```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}' ``` ### Response `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 } } ``` ### Errors | Status | When | | --- | --- | | 400 | invalid: a parameter is wrong; field names it. invalid_url: Not a public https URL on port 443. | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 404 | not_found: no such thing, or not yours. | | 429 | rate_limited: wait Retry-After seconds. | ## Delete a webhook endpoint `DELETE /v1/webhooks/{id}` · Scope: `webhooks:write` Deletes the endpoint and its delivery log. Nothing more is sent to it. ### Parameters | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | path | integer | Yes | The endpoint id. | ### Example request ```bash curl -X DELETE "https://api.hillsmusic.com/v1/webhooks/7" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `200` ```json { "ok": true } ``` ### Errors | Status | When | | --- | --- | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 404 | not_found: no such thing, or not yours. | | 429 | rate_limited: wait Retry-After seconds. | ## Roll a webhook secret `POST /v1/webhooks/{id}/roll-secret` · Scope: `webhooks:write` Makes a new signing secret; the old one stops at once. The new secret is in this answer only. ### Parameters | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | path | integer | Yes | The endpoint id. | ### Example request ```bash curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/roll-secret" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `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" } ``` ### Errors | Status | When | | --- | --- | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 404 | not_found: no such thing, or not yours. | | 429 | rate_limited: wait Retry-After seconds. | ## Send a test event `POST /v1/webhooks/{id}/test` · Scope: `webhooks:write` Queues a webhook.test event to this endpoint, whatever events it has, signed like any other. Its outcome shows in the deliveries. ### Parameters | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | path | integer | Yes | The endpoint id. | ### Example request ```bash curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/test" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `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" } } } } } ``` ### Errors | Status | When | | --- | --- | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 404 | not_found: no such thing, or not yours. | | 409 | endpoint_disabled: The endpoint is off. | | 429 | rate_limited: wait Retry-After seconds. | ## List an endpoint's deliveries `GET /v1/webhooks/{id}/deliveries` · Scope: `webhooks:read` or `webhooks:write` What was sent to the endpoint in the last 30 days, newest first: the payload, attempts, the last HTTP status and time, and the error. ### Parameters | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | path | integer | Yes | The endpoint id. | | `status` | query | `pending` \| `succeeded` \| `failed` | No | Only these. | | `event` | query | string | No | Only this event type. | | `limit` | query | number | No | 1–100, default 50. | | `before` | query | number | No | Deliveries older than this delivery id (the next page). | ### Example request ```bash curl "https://api.hillsmusic.com/v1/webhooks/7/deliveries?status=failed" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `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 } ``` ### Errors | Status | When | | --- | --- | | 400 | invalid: a parameter is wrong; field names it. | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 404 | not_found: no such thing, or not yours. | | 429 | rate_limited: wait Retry-After seconds. | ## Retry a delivery `POST /v1/webhooks/{id}/deliveries/{delivery_id}/retry` · Scope: `webhooks:write` Sends the same event (same id and payload) to the endpoint again now. ### Parameters | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | path | integer | Yes | The endpoint id. | | `delivery_id` | path | integer | Yes | The delivery id. | ### Example request ```bash curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/deliveries/1042/retry" \ -H "Authorization: Bearer $HILLS_API_KEY" ``` ### Response `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" } } } } } ``` ### Errors | Status | When | | --- | --- | | 401 | unauthenticated, invalid_key, key_revoked, key_expired or test_keys_retired. | | 403 | insufficient_scope: the key lacks the scope; scope names it. account_inactive or api_not_in_plan. | | 404 | not_found: no such thing, or not yours. | | 409 | endpoint_disabled: The endpoint is off. | | 429 | rate_limited: wait Retry-After seconds. | Source: https://developer.hillsmusic.com/reference/webhooks/