Webhooks
Recevez les événements en temps réel et vérifiez les signatures HMAC.
À chaque événement notable (notification d'un signataire, OTP envoyé, signature acquise, demande complétée ou expirée), Signlift POSTe un payload JSON signé HMAC-SHA256 sur l'URL configurée pour votre application externe.
Configuration
L'URL de webhook est configurée par application externe dans le dashboard,
au moment où vous créez votre clé API. Le webhook_secret est affiché une
seule fois — stockez-le aux côtés de votre clé API.
Événements
Cinq types d'événements sont émis vers les webhooks aujourd'hui :
| Event | Déclencheur |
|---|---|
signer.notified | Notification d'invitation envoyée à un signataire. |
signer.otp_sent | OTP envoyé à un signataire (e-mail ou SMS). |
signer.signed | Un signataire a finalisé sa signature. |
request.completed | Tous les signataires ont signé. |
request.expired | La demande a dépassé sa fenêtre de validité. |
Headers
Chaque requête entrante porte trois headers Signlift :
| Header | Contenu |
|---|---|
X-Signlift-Event | Type d'événement (ex. request.completed). |
X-Signlift-Delivery | Identifiant unique de la tentative de livraison. Idempotence côté client. |
X-Signlift-Signature | Signature HMAC-SHA256 du body, format sha256=<hex>. |
Le Content-Type est toujours application/json.
Format du payload
{
"event": "request.completed",
"occurred_at": "2026-05-17T15:12:43Z",
"signature_request": {
"id": 42,
"status": "completed",
"mode": "sequential"
},
"signer": {
"id": 1768,
"first_name": "Jeanne",
"last_name": "Dupont",
"full_name": "Jeanne Dupont",
"email": "jeanne@example.com",
"status": "signed"
}
}event: type d'événement (identique au headerX-Signlift-Event).occurred_at: horodatage ISO 8601 UTC.signature_request: toujours présent —id,status,mode.signer: présent uniquement pour les événements liés à un signataire (signer.notified,signer.otp_sent,signer.signed).
Les détails complets d'une demande (signataires, documents, URLs signées) ne
sont pas inclus dans le payload — récupérez-les via
GET /api/v1/signature_requests/:id.
Vérification HMAC
Le header X-Signlift-Signature contient la signature HMAC-SHA256 du body
brut (avant tout parsing JSON), encodée en hexadécimal et préfixée par
sha256=.
require "openssl"
require "active_support/security_utils"
def verify_signlift_webhook(raw_body, header, secret)
expected = "sha256=" + OpenSSL::HMAC.hexdigest("SHA256", secret, raw_body)
ActiveSupport::SecurityUtils.secure_compare(expected, header.to_s)
endimport crypto from "node:crypto"
function verifySignliftWebhook(rawBody, header, secret) {
const expected =
"sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex")
const a = Buffer.from(expected)
const b = Buffer.from(header || "")
return a.length === b.length && crypto.timingSafeEqual(a, b)
}import hmac
import hashlib
def verify_signlift_webhook(raw_body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, header or "")Retry policy
Si votre endpoint répond avec un code HTTP ≠ 2xx, est injoignable, ou met plus de 10 secondes à répondre, Signlift réessaie selon le calendrier suivant :
| Tentative | Délai depuis l'échec précédent |
|---|---|
| 1 | 1 minute |
| 2 | 5 minutes |
| 3 | 25 minutes |
| 4 | 2 heures |
| 5 | 10 heures |
Soit 5 retries au total, sur environ 13 h 30. Après 5 échecs, la livraison
est marquée failed et n'est plus retentée automatiquement.
Idempotence côté client
Votre handler doit être idempotent : un même événement peut être livré plusieurs fois (échec puis retry, double notification réseau, etc.).
Utilisez X-Signlift-Delivery comme clé de déduplication — chaque tentative
porte un identifiant unique, persistez-le côté votre app.
delivery_id = request.headers["X-Signlift-Delivery"]
return head :ok if WebhookEvent.exists?(delivery_id: delivery_id)
WebhookEvent.create!(delivery_id: delivery_id, ...)