Aller au contenu

Événements webhook

Le mécanisme de livraison et les payloads sont identiques pour les deux flux d'intégration (voidsign_mail et caller_embed). Une seule différence : l'événement request.invite_sent n'est émis qu'en flux voidsign_mail, car il correspond à l'e-mail d'invitation, qui n'est pas envoyé en caller_embed. Les relances (request.manual_reminder_sent, request.programmed_reminder_sent) peuvent en revanche survenir dans les deux flux si reminder_days est renseigné. En flux embarqué, votre page parente reçoit en plus un événement postMessage voidsign:signed par signataire ; il n'est pas livré côté serveur. Voir Intégrer la signature sur votre application.

Types d'événements

Événement Description
request.invite_sent L'e-mail d'invitation a été envoyé à un signataire
request.manual_reminder_sent Un e-mail de relance déclenché par un utilisateur depuis la plateforme a été envoyé à un signataire
request.programmed_reminder_sent Un e-mail de relance programmé (planifié) a été envoyé à un signataire
request.partial_signed Un des signataires a signé, cependant la demande n'est pas encore complète
request.completed Tous les signataires ont signé la demande
request.cancelled La demande a été annulée / révoquée
hello Événement de test envoyé lorsque vous vérifiez votre endpoint lors de la configuration/débogage (toujours livré à la demande manuelle)

D'autres types d'événements seront ajoutés à l'avenir. Vous pouvez configurer le webhook pour recevoir tous les types d'événements (actuels et futurs).

Pour les instructions de configuration et la vérification des signatures, consultez Configurer les webhooks.

En-têtes HTTP

VoidSign livre les webhooks sous forme de requêtes POST avec les en-têtes suivants :

En-tête Description
Content-Type application/json
User-Agent VoidSign-Webhook/1.0
webhook-id Identifiant unique de livraison (msg_<uuid>)
webhook-timestamp Horodatage Unix (secondes) de l'envoi de l'événement
webhook-signature Signature HMAC-SHA256 (v1,<base64>)

Exemple de requête HTTP brute :

POST /webhooks/voidsign HTTP/1.1
Host: example.com
Content-Type: application/json
User-Agent: VoidSign-Webhook/1.0
webhook-id: msg_a1b2c3d4-e5f6-7890-abcd-ef1234567890
webhook-timestamp: 1742140948
webhook-signature: v1,U2lnbmF0dXJlIG9mIGEgdm9pZHNpZ24gbWVzc2FnZQ==

{"data":{"metadata":{"order_id":"A-123"},"request_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890"},"timestamp":"2026-03-16T17:42:28+00:00","type":"request.completed"}

Schémas de payload

Chaque payload est un objet JSON comportant un type (le nom de l'événement) et un timestamp (ISO 8601, le moment où l'événement s'est produit). Tous les événements sauf hello comportent également un objet data. Il n'existe que trois formes de data :

Forme de data Événements
request_id + metadata + signer_id request.invite_sent, request.manual_reminder_sent, request.programmed_reminder_sent, request.partial_signed
request_id + metadata request.completed, request.cancelled
aucun champ data hello

Tout événement rattaché à une demande porte le champ metadata : le dictionnaire que vous avez vous-même défini sur cette demande (voir Vos métadonnées). C'est ce qui rend le payload auto-suffisant : vous retrouvez votre propre référence sans appeler l'API. Il vaut null si vous n'avez jamais défini de métadonnées sur la demande, et {} si vous les avez explicitement vidées.

Un exemple par forme (tout autre événement du même groupe est identique, à l'exception de son type) :

request_id + metadata + signer_id :

{
  "type": "request.invite_sent",
  "timestamp": "2026-03-16T17:42:28+00:00",
  "data": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "signer_id": "11111111-2222-3333-4444-555555555555",
    "metadata": {
      "order_id": "A-123"
    }
  }
}

request_id + metadata :

{
  "type": "request.completed",
  "timestamp": "2026-03-16T17:42:28+00:00",
  "data": {
    "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "metadata": {
      "order_id": "A-123"
    }
  }
}

aucun champ data :

{
  "type": "hello",
  "timestamp": "2026-03-16T17:42:28+00:00"
}

Propriétés du payload

  • La valeur du webhook-id est unique pour chaque livraison (un événement envoyé à un endpoint donné, voir le tableau des en-têtes ci-dessus) et reste stable à travers tous les réessais de cette livraison, ceci vous permet d'assurer l'idempotence au sein de votre propre système pour gérer les payloads rejoués.
  • La valeur de l'en-tête webhook-timestamp est l'horodatage utilisé pour la signature mais pas l'horodatage de l'événement. Consultez l'avertissement ci-dessous.
  • La valeur de l'en-tête webhook-signature est la signature attendue de la requête. Consultez Vérifier les signatures.
  • Le type d'événement est toujours fourni dans le corps de la requête au chemin JSON .type.
  • L'horodatage de l'événement est toujours fourni dans le corps de la requête au chemin JSON .timestamp.
  • Les données de l'événement sont toujours fournies dans le corps de la requête au chemin JSON .data. Les schémas spécifiques dépendent du type d'événement.

Horodatage des données vs horodatage du webhook

  • L'horodatage des données, c'est-à-dire l'horodatage présent dans le corps de la requête, représente le moment où l'événement s'est produit (par exemple, quand le dernier signataire a signé).
  • L'horodatage du webhook, c'est-à-dire la valeur de l'en-tête webhook-timestamp, correspond au moment où la livraison a été tentée par les serveurs VoidSign.

Comportement de réessai

Si votre endpoint ne retourne pas une réponse 2xx, VoidSign retente la livraison avec un backoff exponentiel sur de courtes durées, puis un backoff linéaire sur de plus longues durées. Les livraisons qui ne peuvent pas être complétées sont finalement abandonnées.

Votre endpoint doit être idempotent : utilisez l'en-tête webhook-id pour détecter les livraisons en double et éviter de traiter le même événement deux fois.

Le corps d'une livraison ne change jamais

Le champ metadata porte les métadonnées telles qu'elles étaient au moment où VoidSign a émis l'événement, et non telles qu'elles sont aujourd'hui. Pour les événements de signature et d'annulation (request.partial_signed, request.completed, request.cancelled), l'émission coïncide avec le timestamp du corps à quelques millisecondes près. Pour les trois événements adossés à un e-mail (request.invite_sent, request.manual_reminder_sent, request.programmed_reminder_sent), l'émission peut suivre l'envoi effectif de l'e-mail (le timestamp du corps) d'un délai pouvant atteindre environ une heure : un PATCH effectué dans cette fenêtre est reflété dans le metadata de l'événement.

Toutes les tentatives et tous les réessais d'une même livraison portent le même corps, à l'octet près : même timestamp (celui du corps ; l'en-tête webhook-timestamp, lui, change à chaque tentative, voir l'avertissement ci-dessus), même metadata. Un appel à PATCH /api/v1/requests/{request_id} ne modifie pas les événements déjà émis ; il n'affecte que ceux émis après lui. Vous pouvez donc dédupliquer sur webhook-id en toute sécurité : quelle que soit la tentative que vous conservez, vous conservez la même information.

Deux précisions :

  • Si plusieurs de vos endpoints sont abonnés au même événement, chacun reçoit sa propre livraison, sous son propre webhook-id (le corps, lui, est identique d'un endpoint à l'autre).
  • Pour les trois événements adossés à un e-mail, un même événement réel peut exceptionnellement donner lieu à deux livraisons distinctes, chacune avec son webhook-id. Si votre traitement n'est pas naturellement idempotent, dédupliquez alors sur (type, request_id, signer_id, timestamp).

Pour connaître les métadonnées courantes d'une demande, lisez GET /api/v1/requests/{request_id}.

Calendrier de réessai

Le calendrier exact de réessai pourra être mis à jour à l'avenir pour s'aligner sur la spécification de réessai Standard Webhooks.