Skip to content
HILLS API v1 Early access

API reference

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

curl "https://api.hillsmusic.com/v1/webhooks/events" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 200

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

curl "https://api.hillsmusic.com/v1/webhooks" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 200

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

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

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

curl "https://api.hillsmusic.com/v1/webhooks/7" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 200

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

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

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

curl -X DELETE "https://api.hillsmusic.com/v1/webhooks/7" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 200

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

curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/roll-secret" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 200

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

curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/test" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 202

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

curl "https://api.hillsmusic.com/v1/webhooks/7/deliveries?status=failed" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 200

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

curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/deliveries/1042/retry" \
  -H "Authorization: Bearer $HILLS_API_KEY"

Response 202

{
  "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.

Ready to integrate?

Request API access and we get back to you within 1–3 business days.