Aller au contenu

Webhooks

Abonnez-vous aux événements XID et recevez des payloads HTTP signés lorsque les utilisateurs, sessions et organisations changent.

Afficher en Markdown

Nommage des événements

Les événements suivent le modèle <object>.<action>. Chaque événement porte un nom de type stable, un svix-id unique et un horodatage ISO 8601.

Objet Opérations
user created, updated, deleted
session created, ended, removed, revoked
organization created, updated, deleted
organizationMembership created, updated, deleted
organizationInvitation created, accepted, revoked
organizationDomain created, updated, deleted, verified, verification_failed
authentication password_succeeded, password_failed, passkey_succeeded, passkey_failed, mfa_succeeded, mfa_failed, oauth_succeeded, oauth_failed, sso_succeeded, sso_failed, magic_auth_succeeded, magic_auth_failed, email_verification_succeeded, email_verification_failed, radar_risk_detected
connection activated, deactivated, deleted, saml_certificate_renewed, renewal_required
dsync activated, deleted, user.created, user.updated, user.deleted, group.created, group.updated, group.deleted, group.user_added, group.user_removed
role created, updated, deleted
permission created, updated, deleted
email created (déclenché lorsque le développeur prend en charge l’envoi)
sms created (déclenché lorsque le développeur prend en charge l’envoi)
billing subscription.created, subscription.updated, paymentAttempt.succeeded, paymentAttempt.failed

Structure du payload

Chaque livraison de webhook est un HTTP POST avec Content-Type: application/json. Le corps contient type, data et des en-têtes de métadonnées de niveau supérieur.

{
  "type": "user.created",
  "data": {
    "id": "usr_01abc",
    "email_addresses": [{ "email_address": "alice@example.com" }],
    "created_at": 1700000000000
  }
}

Vérification de signature

XID signe chaque livraison avec HMAC-SHA256. Vérifiez la signature avant de traiter le payload. Rejetez les livraisons de plus de 5 minutes pour prévenir les attaques par rejeu.

En-tête Description
svix-id Identifiant unique du message. Utilisez-le pour dédupliquer les livraisons relancées.
svix-timestamp Secondes Unix indiquant quand le message a été envoyé.
svix-signature HMAC-SHA256 encodé en Base64 de ${svix-id}.${svix-timestamp}.${raw-body} en utilisant le secret de signature du point de terminaison.
// Node.js / Cloudflare Workers example
async function verifyWebhook(request, secret) {
  const svixId = request.headers.get('svix-id')
  const svixTimestamp = request.headers.get('svix-timestamp')
  const svixSignature = request.headers.get('svix-signature')
  const body = await request.text()

  // Reject messages older than 5 minutes
  const ts = Number(svixTimestamp)
  if (Math.abs(Date.now() / 1000 - ts) > 300) {
    throw new Error('webhook timestamp out of tolerance')
  }

  const signedContent = `${svixId}.${svixTimestamp}.${body}`
  const keyData = Uint8Array.from(atob(secret), c => c.charCodeAt(0))
  const key = await crypto.subtle.importKey(
    'raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['verify']
  )
  const msgData = new TextEncoder().encode(signedContent)

  // svix-signature may contain multiple comma-separated values
  for (const sig of svixSignature.split(' ')) {
    const prefix = 'v1,'
    if (!sig.startsWith(prefix)) continue
    const sigBytes = Uint8Array.from(atob(sig.slice(prefix.length)), c => c.charCodeAt(0))
    const valid = await crypto.subtle.verify('HMAC', key, sigBytes, msgData)
    if (valid) return JSON.parse(body)
  }
  throw new Error('invalid webhook signature')
}

Relances et dead letters

  • Les livraisons échouées sont relancées avec un backoff exponentiel. Après le nombre maximum de tentatives, le message est écrit dans le dead-letter store D1 pour inspection manuelle.
  • La livraison est découplée du chemin d’authentification via les Cloudflare Queues. Un endpoint lent ou indisponible n’affecte pas la latence de connexion.
  • Utilisez l’en-tête svix-id pour dédupliquer les livraisons de votre côté. Les relances portent le même svix-id que la tentative d’origine.
flowchart LR
  XID --> Queue
  Queue -->|HTTPS| Endpoint
  Endpoint -->|2xx| ACK
  Endpoint -->|non-2xx| Retry
  Retry --> Queue
  Retry -->|max_retries| dlq["D1 DLQ"]

Relecture manuelle

Utilisez POST /v1/webhooks/:endpointId/replay pour rejouer des événements par ID de message ou plage de temps. Les événements rejoués portent de nouvelles valeurs svix-id mais conservent les type et data d’origine.

# Replay events from the last hour
curl -X POST https://xid.dev/v1/webhooks/whe_xxx/replay \
  -H 'Authorization: Bearer sk_live_xxx' \
  -H 'Content-Type: application/json' \
  -d '{ "since": "2024-01-01T00:00:00Z", "until": "2024-01-01T01:00:00Z" }'

API d’événements

En plus des webhooks push, XID expose un flux d’événements ordonné et immuable avec pagination par curseur via GET /v1/events. Tirez le flux pour construire une synchronisation fiable sans manquer d’événements entre les relances de webhook.

curl 'https://xid.dev/v1/events?limit=100&after=evt_xxx' \
  -H 'Authorization: Bearer sk_live_xxx'
Navigation

Saisissez votre recherche...

Utilisez les touches fléchées pour naviguerAppuyez sur Entrée pour sélectionnerAppuyez sur Échap pour fermer