Aller au contenu

Référence API

Webhooks

Enregistrez et gérez les points de terminaison auxquels SMSend livre les événements.

Lister les points de terminaison webhook

GET/public/v1/webhooks

Renvoie tous les points de terminaison enregistrés sur le compte, du plus récent au plus ancien, avec leur santé actuelle.

Portée requise WEBHOOKS_MANAGE

Requête

curl https://api.smsend.net/public/v1/webhooks \
  -H "Authorization: Bearer $SMSEND_API_KEY"
<?php

$webhooks = Http::withToken(getenv('SMSEND_API_KEY'))
    ->get('https://api.smsend.net/public/v1/webhooks')
    ->json('data.webhooks');
const response = await fetch('https://api.smsend.net/public/v1/webhooks', {
  headers: { Authorization: `Bearer ${process.env.SMSEND_API_KEY}` },
})

const { data } = await response.json()
import os
import requests

webhooks = requests.get(
    "https://api.smsend.net/public/v1/webhooks",
    headers={"Authorization": f"Bearer {os.environ['SMSEND_API_KEY']}"},
).json()["data"]["webhooks"]

Réponses

200Les points de terminaison webhook du compte. Les secrets ne sont jamais inclus dans une lecture.
{
  "data": {
    "webhooks": [
      {
        "webhook_id": "01K3F8ZZ1122334455667788AA",
        "url": "https://hooks.example.bf/smsend",
        "description": "Production receipts",
        "events": ["MESSAGE_TERMINAL", "BATCH_SETTLED"],
        "status": "ENABLED",
        "consecutive_failures": 0,
        "disabled_reason": null,
        "last_success_at": "2026-08-23T14:05:20+00:00",
        "last_failure_at": null,
        "created_at": "2026-07-02T08:31:44+00:00"
      }
    ]
  }
}

Erreurs possibles

CodeStatutSignification
UNAUTHORIZED401Aucune clé, une clé malformée, un mauvais secret, une clé révoquée ou expirée, ou un compte suspendu. Tous indiscernables par construction.
INSUFFICIENT_SCOPE403La clé est valide mais ne porte pas la portée exigée par ce point de terminaison. La portée est nommée dans le detail.
RATE_LIMITED429La limite de requêtes de la clé a été dépassée. Attendez l’intervalle indiqué dans Retry-After.
INTERNAL_ERROR500Une défaillance inattendue du côté de SMSend. Citez l’identifiant de requête à l’assistance.

Créer un point de terminaison webhook

POST/public/v1/webhooks

Enregistre un point de terminaison et émet son secret de signature. C’est la seule réponse qui contienne jamais le secret.

Portée requise WEBHOOKS_MANAGE

Paramètres du corps

urlstringObligatoire

Où livrer les événements. Doit être en HTTPS et ne doit pas se résoudre vers une adresse privée, de bouclage ou de lien local. Un nom d’hôte dont le DNS n’a pas encore propagé est accepté.

max 2048 characters, must be HTTPS, no private or loopback address

descriptionstringOptionnel

Un libellé pour votre propre usage, affiché dans l’espace client.

max 255 characters

eventsarrayOptionnel

Quels événements livrer. Les doublons sont supprimés ; un tableau vide retombe sur la valeur par défaut.

default ["MESSAGE_TERMINAL", "BATCH_SETTLED"]

Requête

curl -X POST https://api.smsend.net/public/v1/webhooks \
  -H "Authorization: Bearer $SMSEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.example.bf/smsend",
    "description": "Production receipts",
    "events": ["MESSAGE_TERMINAL", "BATCH_SETTLED", "BATCH_ACCEPTED"]
  }'
<?php

$webhook = Http::withToken(getenv('SMSEND_API_KEY'))
    ->post('https://api.smsend.net/public/v1/webhooks', [
        'url' => 'https://hooks.example.bf/smsend',
        'description' => 'Production receipts',
        'events' => ['MESSAGE_TERMINAL', 'BATCH_SETTLED', 'BATCH_ACCEPTED'],
    ])
    ->json('data');

// The only response that ever carries the secret. Store it now.
storeWebhookSecret($webhook['webhook_id'], $webhook['secret']);
const response = await fetch('https://api.smsend.net/public/v1/webhooks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SMSEND_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://hooks.example.bf/smsend',
    description: 'Production receipts',
    events: ['MESSAGE_TERMINAL', 'BATCH_SETTLED', 'BATCH_ACCEPTED'],
  }),
})

const { data } = await response.json()

// The only response that ever carries the secret. Store it now.
storeWebhookSecret(data.webhook_id, data.secret)
import os
import requests

webhook = requests.post(
    "https://api.smsend.net/public/v1/webhooks",
    headers={"Authorization": f"Bearer {os.environ['SMSEND_API_KEY']}"},
    json={
        "url": "https://hooks.example.bf/smsend",
        "description": "Production receipts",
        "events": ["MESSAGE_TERMINAL", "BATCH_SETTLED", "BATCH_ACCEPTED"],
    },
).json()["data"]

# The only response that ever carries the secret. Store it now.
store_webhook_secret(webhook["webhook_id"], webhook["secret"])

Réponses

201Le point de terminaison, secret compris. Stockez le secret maintenant — il ne pourra plus être récupéré.
{
  "data": {
    "webhook_id": "01K3F8ZZ1122334455667788AA",
    "url": "https://hooks.example.bf/smsend",
    "description": "Production receipts",
    "events": ["MESSAGE_TERMINAL", "BATCH_SETTLED", "BATCH_ACCEPTED"],
    "status": "ENABLED",
    "consecutive_failures": 0,
    "disabled_reason": null,
    "last_success_at": null,
    "last_failure_at": null,
    "created_at": "2026-08-23T14:22:07+00:00",
    "secret": "whsec_3f8a1c9e0b7d452a6e18cf30b95d7e421ac6f08b3d92e574a10c8fb26d94e753"
  }
}

Erreurs possibles

CodeStatutSignification
VALIDATION_FAILED422La requête était malformée : un paramètre manquant ou invalide, une longueur de clé d’idempotence incorrecte, une URL de webhook rejetée, ou une méthode ou un type de contenu non pris en charge.
UNAUTHORIZED401Aucune clé, une clé malformée, un mauvais secret, une clé révoquée ou expirée, ou un compte suspendu. Tous indiscernables par construction.
INSUFFICIENT_SCOPE403La clé est valide mais ne porte pas la portée exigée par ce point de terminaison. La portée est nommée dans le detail.
RATE_LIMITED429La limite de requêtes de la clé a été dépassée. Attendez l’intervalle indiqué dans Retry-After.
INTERNAL_ERROR500Une défaillance inattendue du côté de SMSend. Citez l’identifiant de requête à l’assistance.

Renouveler le secret de signature

POST/public/v1/webhooks/{webhook_id}/rotate

Émet un nouveau secret et garde le précédent valide pendant 24 heures. Les deux permettent la vérification pendant la fenêtre, tandis que SMSend signe avec le nouveau : vous pouvez donc déployer sans perdre de livraisons.

Portée requise WEBHOOKS_MANAGE

Paramètres de chemin

webhook_idstringObligatoire

L’identifiant du point de terminaison, renvoyé à sa création.

26-character ULID

Requête

curl -X POST https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/rotate \
  -H "Authorization: Bearer $SMSEND_API_KEY"
<?php

$webhook = Http::withToken(getenv('SMSEND_API_KEY'))
    ->post('https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/rotate')
    ->json('data');
const response = await fetch(
  'https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/rotate',
  { method: 'POST', headers: { Authorization: `Bearer ${process.env.SMSEND_API_KEY}` } },
)

const { data } = await response.json()
import os
import requests

webhook = requests.post(
    "https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/rotate",
    headers={"Authorization": f"Bearer {os.environ['SMSEND_API_KEY']}"},
).json()["data"]

Réponses

200Le point de terminaison avec son nouveau secret, et le moment où l’ancien cesse de fonctionner.
{
  "data": {
    "webhook_id": "01K3F8ZZ1122334455667788AA",
    "url": "https://hooks.example.bf/smsend",
    "description": "Production receipts",
    "events": ["MESSAGE_TERMINAL", "BATCH_SETTLED"],
    "status": "ENABLED",
    "consecutive_failures": 0,
    "disabled_reason": null,
    "last_success_at": "2026-08-23T14:05:20+00:00",
    "last_failure_at": null,
    "created_at": "2026-07-02T08:31:44+00:00",
    "secret": "whsec_a71b40e2c6d9385f1e02ba7c48d3906fe25b1837cd04a96e2f7b58c103da4e61",
    "previous_secret_expires_at": "2026-08-24T14:22:07+00:00"
  }
}

Erreurs possibles

CodeStatutSignification
NOT_FOUND404Ressource inexistante — y compris une ressource appartenant à un autre compte, délibérément indiscernable d’une ressource qui n’a jamais existé.
UNAUTHORIZED401Aucune clé, une clé malformée, un mauvais secret, une clé révoquée ou expirée, ou un compte suspendu. Tous indiscernables par construction.
INSUFFICIENT_SCOPE403La clé est valide mais ne porte pas la portée exigée par ce point de terminaison. La portée est nommée dans le detail.
RATE_LIMITED429La limite de requêtes de la clé a été dépassée. Attendez l’intervalle indiqué dans Retry-After.
INTERNAL_ERROR500Une défaillance inattendue du côté de SMSend. Citez l’identifiant de requête à l’assistance.

Activer un point de terminaison

POST/public/v1/webhooks/{webhook_id}/enable

Réactive un point de terminaison désactivé et remet son compteur d’échecs à zéro, pour qu’un point de terminaison rétabli ne soit pas de nouveau coupé par le premier échec suivant son retour.

Portée requise WEBHOOKS_MANAGE

Paramètres de chemin

webhook_idstringObligatoire

L’identifiant du point de terminaison, renvoyé à sa création.

26-character ULID

Requête

curl -X POST https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/enable \
  -H "Authorization: Bearer $SMSEND_API_KEY"
<?php

$webhook = Http::withToken(getenv('SMSEND_API_KEY'))
    ->post('https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/enable')
    ->json('data');
const response = await fetch(
  'https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/enable',
  { method: 'POST', headers: { Authorization: `Bearer ${process.env.SMSEND_API_KEY}` } },
)

const { data } = await response.json()
import os
import requests

webhook = requests.post(
    "https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/enable",
    headers={"Authorization": f"Bearer {os.environ['SMSEND_API_KEY']}"},
).json()["data"]

Réponses

200Le point de terminaison réactivé.
{
  "data": {
    "webhook_id": "01K3F8ZZ1122334455667788AA",
    "url": "https://hooks.example.bf/smsend",
    "description": "Production receipts",
    "events": ["MESSAGE_TERMINAL", "BATCH_SETTLED"],
    "status": "ENABLED",
    "consecutive_failures": 0,
    "disabled_reason": null,
    "last_success_at": "2026-08-23T14:05:20+00:00",
    "last_failure_at": "2026-08-23T18:40:02+00:00",
    "created_at": "2026-07-02T08:31:44+00:00"
  }
}

Erreurs possibles

CodeStatutSignification
NOT_FOUND404Ressource inexistante — y compris une ressource appartenant à un autre compte, délibérément indiscernable d’une ressource qui n’a jamais existé.
UNAUTHORIZED401Aucune clé, une clé malformée, un mauvais secret, une clé révoquée ou expirée, ou un compte suspendu. Tous indiscernables par construction.
INSUFFICIENT_SCOPE403La clé est valide mais ne porte pas la portée exigée par ce point de terminaison. La portée est nommée dans le detail.
RATE_LIMITED429La limite de requêtes de la clé a été dépassée. Attendez l’intervalle indiqué dans Retry-After.
INTERNAL_ERROR500Une défaillance inattendue du côté de SMSend. Citez l’identifiant de requête à l’assistance.

Désactiver un point de terminaison

POST/public/v1/webhooks/{webhook_id}/disable

Arrête la livraison vers un point de terminaison sans le supprimer. Les événements créés pendant sa désactivation ne sont pas mis en file d’attente pour plus tard — récupérez-les depuis le flux des messages.

Portée requise WEBHOOKS_MANAGE

Paramètres de chemin

webhook_idstringObligatoire

L’identifiant du point de terminaison, renvoyé à sa création.

26-character ULID

Requête

curl -X POST https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/disable \
  -H "Authorization: Bearer $SMSEND_API_KEY"
<?php

$webhook = Http::withToken(getenv('SMSEND_API_KEY'))
    ->post('https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/disable')
    ->json('data');
const response = await fetch(
  'https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/disable',
  { method: 'POST', headers: { Authorization: `Bearer ${process.env.SMSEND_API_KEY}` } },
)

const { data } = await response.json()
import os
import requests

webhook = requests.post(
    "https://api.smsend.net/public/v1/webhooks/01K3F8ZZ1122334455667788AA/disable",
    headers={"Authorization": f"Bearer {os.environ['SMSEND_API_KEY']}"},
).json()["data"]

Réponses

200Le point de terminaison désactivé.
{
  "data": {
    "webhook_id": "01K3F8ZZ1122334455667788AA",
    "url": "https://hooks.example.bf/smsend",
    "description": "Production receipts",
    "events": ["MESSAGE_TERMINAL", "BATCH_SETTLED"],
    "status": "DISABLED_BY_USER",
    "consecutive_failures": 0,
    "disabled_reason": "Disabled by the account.",
    "last_success_at": "2026-08-23T14:05:20+00:00",
    "last_failure_at": null,
    "created_at": "2026-07-02T08:31:44+00:00"
  }
}

Erreurs possibles

CodeStatutSignification
NOT_FOUND404Ressource inexistante — y compris une ressource appartenant à un autre compte, délibérément indiscernable d’une ressource qui n’a jamais existé.
UNAUTHORIZED401Aucune clé, une clé malformée, un mauvais secret, une clé révoquée ou expirée, ou un compte suspendu. Tous indiscernables par construction.
INSUFFICIENT_SCOPE403La clé est valide mais ne porte pas la portée exigée par ce point de terminaison. La portée est nommée dans le detail.
RATE_LIMITED429La limite de requêtes de la clé a été dépassée. Attendez l’intervalle indiqué dans Retry-After.
INTERNAL_ERROR500Une défaillance inattendue du côté de SMSend. Citez l’identifiant de requête à l’assistance.

Statuts de point de terminaison

Les deux états désactivés sont distingués à dessein : l’un est une décision que vous avez prise, l’autre un échec sur lequel vous devez enquêter, et ils appellent des réactions différentes.

ValeurSignification
ENABLED
Reçoit les livraisons.
DISABLED_BY_USER
Mis en pause par le compte. Réactivez-le quand vous êtes prêt.
DISABLED_AFTER_FAILURES
Coupé par SMSend après 20 échecs consécutifs. Réparez le point de terminaison, puis réactivez-le explicitement.

Pas sur cette surface

Modifier l’URL d’un point de terminaison, ses abonnements aux événements ou sa description, et supprimer complètement un point de terminaison, se font dans l’espace client plutôt que par l’API. La création et la révocation des clés API sont de même réservées à l’espace client — un point de terminaison public de création de clés transformerait une seule clé divulguée en accès permanent.