Signlift

Webhooks

Recevez les événements en temps réel et vérifiez les signatures HMAC.

Configuration

Passez webhook_url lors de la création d'une signature request, ou configurez une URL globale au niveau de l'organisation dans le dashboard.

{
  "webhook_url": "https://yourapp.com/webhooks/signlift",
  "...": "..."
}

Événements

EventDéclencheur
signature_request.createdCréation de la requête.
signer.notifiedEmail/SMS d'invitation envoyé.
signer.signedUn signataire a signé (utile en mode séquentiel).
signature_request.completedTous les signataires ont signé.
signature_request.completion_notifiedEmails de complétion envoyés au demandeur/signataires.
signature_request.expiredLa requête a dépassé validity_days.

Format du payload

{
  "event": "signature_request.completed",
  "occurred_at": "2026-05-16T15:12:43Z",
  "data": {
    "signature_request_id": "sr_01HZQM...",
    "signed_at": "2026-05-16T15:12:43Z",
    "documents": [
      { "id": "doc_01HZQK...", "signed_pdf_url": "https://..." }
    ]
  }
}

Vérification HMAC

Chaque webhook contient un header X-Signlift-Signature au format t=TIMESTAMP,v1=HMAC_HEX. Calculez le HMAC SHA-256 de ${TIMESTAMP}.${RAW_BODY} avec votre webhook secret, et comparez en temps constant.

require 'openssl'

def verify_signlift_webhook(raw_body, header, secret)
  parts = header.split(',').to_h { |p| p.split('=', 2) }
  expected = OpenSSL::HMAC.hexdigest('SHA256', secret, "#{parts['t']}.#{raw_body}")
  Rack::Utils.secure_compare(expected, parts['v1'])
end
import crypto from 'node:crypto'

function verifySignliftWebhook(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${parts.t}.${rawBody}`)
    .digest('hex')
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
}

Retry policy

En cas d'échec (HTTP ≠ 2xx ou timeout 10s), Signlift retente avec backoff exponentiel : immédiat, 30s, 2min, 10min, 1h, puis abandon. Tous les essais sont visibles dans le dashboard.

Pour la robustesse, votre handler doit être idempotent (déduplication via event_id inclus dans le payload).

On this page