# Webhooks
> Les endpoints appelés par HILLS Music à chaque événement : sorties, livraisons, DDEX, relevés, versements, demandes et support en direct. Signés, relancés.
Les endpoints appelés par HILLS Music à chaque événement : sorties, livraisons, DDEX, relevés, versements, demandes et support en direct. Signés, relancés.
URL de base `https://api.hillsmusic.com/v1`. Chaque requête envoie une clé d’API : `Authorization: Bearer hm_live_…`.
- Lister les types d’événements webhook
- Lister les endpoints webhook
- Créer un endpoint webhook
- Obtenir un endpoint webhook
- Modifier un endpoint webhook
- Supprimer un endpoint webhook
- Renouveler le secret d’un webhook
- Envoyer un événement de test
- Lister les livraisons d’un endpoint
- Relancer une livraison
## Lister les types d’événements webhook
`GET /v1/webhooks/events` · Scope : `webhooks:read` ou `webhooks:write`
Tous les types d’événements auxquels un endpoint peut s’abonner, avec leur signification. Les payloads sont documentés sous webhooks dans cette référence.
### Exemple de requête
```bash
curl "https://api.hillsmusic.com/v1/webhooks/events" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `200`
```json
{
"data": [
{
"type": "release.approved",
"label": "Release approved",
"description": "A release was approved and is queued for its stores."
}
]
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Lister les endpoints webhook
`GET /v1/webhooks` · Scope : `webhooks:read` ou `webhooks:write`
Vos endpoints webhook (20 au maximum), du plus ancien au plus récent. Le secret n’est jamais listé.
### Exemple de requête
```bash
curl "https://api.hillsmusic.com/v1/webhooks" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `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
}
]
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Créer un endpoint webhook
`POST /v1/webhooks` · Scope : `webhooks:write`
Enregistre une URL https pour les événements choisis. La réponse contient le secret de signature, une seule fois. L’URL doit être publique : les adresses privées, locales et de métadonnées sont refusées.
### Corps de la requête
JSON.
| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `url` | string | Oui | Où envoyer les événements en POST : une URL https:// publique sur le port 443. |
| `description` | string | Non | Une note pour vous, par exemple le système qui les reçoit. |
| `events` | array | Oui | Les types d’événements à envoyer (voir Webhooks dans cette référence). |
| `enabled` | boolean | Non | true par défaut. |
### Exemple de requête
```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"]}'
```
### Réponse `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"
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 400 | invalid : un paramètre est incorrect ; field l’indique. invalid_url : pas une URL https publique sur le port 443. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 409 | too_many : il existe déjà 20 endpoints. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Obtenir un endpoint webhook
`GET /v1/webhooks/{id}` · Scope : `webhooks:read` ou `webhooks:write`
Un endpoint avec son état de santé : dernier succès et dernier échec, tentatives échouées consécutives et raison de sa désactivation.
### Paramètres
| Paramètre | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | Oui | L’identifiant de l’endpoint. |
### Exemple de requête
```bash
curl "https://api.hillsmusic.com/v1/webhooks/7" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `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
}
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 404 | not_found : la ressource n’existe pas ou ne vous appartient pas. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Modifier un endpoint webhook
`PATCH /v1/webhooks/{id}` · Scope : `webhooks:write`
Modifie son URL, sa description, ses événements, ou le désactive et le réactive (enabled). La réactivation remet son compteur d’échecs à zéro ; les livraisons abandonnées pendant sa désactivation peuvent être renvoyées avec retry.
### Paramètres
| Paramètre | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | Oui | L’identifiant de l’endpoint. |
### Corps de la requête
JSON.
| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `url` | string | Non | Où envoyer les événements en POST : une URL https:// publique sur le port 443. |
| `description` | string | Non | Une note pour vous, par exemple le système qui les reçoit. |
| `events` | array | Non | Les types d’événements à envoyer (voir Webhooks dans cette référence). |
| `enabled` | boolean | Non | false le désactive ; true le réactive. |
### Exemple de requête
```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}'
```
### Réponse `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
}
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 400 | invalid : un paramètre est incorrect ; field l’indique. invalid_url : pas une URL https publique sur le port 443. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 404 | not_found : la ressource n’existe pas ou ne vous appartient pas. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Supprimer un endpoint webhook
`DELETE /v1/webhooks/{id}` · Scope : `webhooks:write`
Supprime l’endpoint et son journal de livraisons. Plus rien ne lui est envoyé.
### Paramètres
| Paramètre | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | Oui | L’identifiant de l’endpoint. |
### Exemple de requête
```bash
curl -X DELETE "https://api.hillsmusic.com/v1/webhooks/7" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `200`
```json
{
"ok": true
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 404 | not_found : la ressource n’existe pas ou ne vous appartient pas. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Renouveler le secret d’un webhook
`POST /v1/webhooks/{id}/roll-secret` · Scope : `webhooks:write`
Génère un nouveau secret de signature ; l’ancien cesse de fonctionner immédiatement. Le nouveau secret ne figure que dans cette réponse.
### Paramètres
| Paramètre | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | Oui | L’identifiant de l’endpoint. |
### Exemple de requête
```bash
curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/roll-secret" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `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"
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 404 | not_found : la ressource n’existe pas ou ne vous appartient pas. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Envoyer un événement de test
`POST /v1/webhooks/{id}/test` · Scope : `webhooks:write`
Met en file d’attente un événement webhook.test pour cet endpoint, quels que soient ses événements, signé comme n’importe quel autre. Son résultat apparaît dans les livraisons.
### Paramètres
| Paramètre | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | Oui | L’identifiant de l’endpoint. |
### Exemple de requête
```bash
curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/test" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `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"
}
}
}
}
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 404 | not_found : la ressource n’existe pas ou ne vous appartient pas. |
| 409 | endpoint_disabled : l’endpoint est désactivé. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Lister les livraisons d’un endpoint
`GET /v1/webhooks/{id}/deliveries` · Scope : `webhooks:read` ou `webhooks:write`
Ce qui a été envoyé à l’endpoint au cours des 30 derniers jours, du plus récent au plus ancien : le payload, les tentatives, le dernier statut HTTP et son heure, et l’erreur.
### Paramètres
| Paramètre | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | Oui | L’identifiant de l’endpoint. |
| `status` | query | `pending` \| `succeeded` \| `failed` | Non | Uniquement celles-ci. |
| `event` | query | string | Non | Uniquement ce type d’événement. |
| `limit` | query | number | Non | 1–100, 50 par défaut. |
| `before` | query | number | Non | Les livraisons antérieures à cet identifiant de livraison (la page suivante). |
### Exemple de requête
```bash
curl "https://api.hillsmusic.com/v1/webhooks/7/deliveries?status=failed" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `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
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 400 | invalid : un paramètre est incorrect ; field l’indique. |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 404 | not_found : la ressource n’existe pas ou ne vous appartient pas. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
## Relancer une livraison
`POST /v1/webhooks/{id}/deliveries/{delivery_id}/retry` · Scope : `webhooks:write`
Renvoie immédiatement le même événement (même id et même payload) à l’endpoint.
### Paramètres
| Paramètre | Emplacement | Type | Obligatoire | Description |
| --- | --- | --- | --- | --- |
| `id` | path | integer | Oui | L’identifiant de l’endpoint. |
| `delivery_id` | path | integer | Oui | L’identifiant de la livraison. |
### Exemple de requête
```bash
curl -X POST "https://api.hillsmusic.com/v1/webhooks/7/deliveries/1042/retry" \
-H "Authorization: Bearer $HILLS_API_KEY"
```
### Réponse `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"
}
}
}
}
}
```
### Erreurs
| Statut | Quand |
| --- | --- |
| 401 | unauthenticated, invalid_key, key_revoked, key_expired ou test_keys_retired. |
| 403 | insufficient_scope : la clé n’a pas le scope requis ; scope l’indique. account_inactive ou api_not_in_plan. |
| 404 | not_found : la ressource n’existe pas ou ne vous appartient pas. |
| 409 | endpoint_disabled : l’endpoint est désactivé. |
| 429 | rate_limited : attendez le nombre de secondes indiqué par Retry-After. |
Source: https://developer.hillsmusic.com/fr/reference/webhooks/