Webhooks notify your server when envelopes are completed, declined, or voided.
Notification channels
Choose how Abundera Sign tells you about activity on your envelopes.
Webhook Events
Subscribe to specific events via the notify_events array when creating envelopes. If omitted, all events are delivered to your callback_url.
| Event | Trigger | Payload |
|---|---|---|
signer.viewed | Signer opens the signing page | Envelope ID, signer email, view count, IP, user agent |
signer.signed | Individual signer completes signing | Envelope ID, signer details, signature type, signed_at |
signer.declined | Signer declines to sign | Envelope ID, signer email, decline reason |
signer.delegated | Signer delegates to another person | Envelope ID, original signer, delegate email/name, reason |
envelope.completed | All signers have signed (document sealed) | Envelope ID, all signer details, download URL |
envelope.voided | Sender voids the document | Envelope ID, void reason, voided_by |
envelope.expired | Document passes its expiration date | Envelope ID, expired_at, unsigned signers |
envelope.extended | Sender extends the signing deadline (revives expired documents) | Envelope ID, previous status, old and new deadline |
payment.completed | Signer completes Stripe payment | Envelope ID, signer email, amount, currency |
clause.flagged | Signer flags a clause for negotiation | Envelope ID, clause text, signer email, reason |
clause.responded | Sender responds to a flagged clause | Envelope ID, clause text, response, status |
clause.accepted | Counter-proposal accepted by signer | |
clause.applied | Agreed clause text applied; signatures re-collected | Envelope ID, clause text, accepted terms |
clause.counter_proposed | Sender sends a counter-proposal | Envelope ID, clause text, counter-proposal text |
clause.withdrawn | Signer withdrew their own open clause flag | Envelope ID, clause text, counter-proposal text |
notarization.completed | Remote online notarization session completes | Envelope ID, notarization ID, notarized PDF URL |
notarization.failed | Remote online notarization session fails | Envelope ID, notarization ID, failure reason |
notarization.expired | Notarization session expires before completion | Envelope ID, notarization ID, expired_at |
signer.idv_verified | Signer passes provider ID verification | Envelope ID, signer email, document type, country |
signer.idv_failed | Signer's ID verification is declined or not approved | Envelope ID, signer email, status, reason |
signer.kba_failed | Signer fails the knowledge-based identity quiz | Envelope ID, signer email, attempts |
signer.otp_locked | Signer is locked out after repeated SMS code failures | Envelope ID, signer email, locked_until |
signer.blocked | Signer is blocked by a signing gate (location, access code, SMS cap, identity checks, or credits) | Envelope ID, signer email, gate, reason |
signer.email_bounced | An email to the signer bounces or draws a spam complaint | Envelope ID, signer email, bounce_type, template_alias |
envelope.retention_expiring | A completed document's evidence purges within 30 days (retention warning) | Envelope ID, purge_date, retention_years |
envelope.purged | Retention period completed; evidence and signer data permanently erased | Envelope ID, retention_years, completed_at |
signer.attachment_uploaded | Signer uploads a supporting attachment | Envelope ID, signer email, filename, size |
payment.declined | A pay-to-sign or overage charge is declined | Envelope ID, amount, currency, reason |
envelope.expiring | Envelope is approaching its expiration date without completing | Envelope ID, expires_at, days_remaining |
HMAC Verification
Deliveries are signed with the Standard Webhooks scheme. Each request carries three headers: webhook-id (unique per delivery, use it to deduplicate), webhook-timestamp (unix seconds), and webhook-signature. The signature is v1,<base64(HMAC-SHA256)> over the signed content {id}.{timestamp}.{rawBody}, keyed by the base64 bytes of your whsec_ secret. The header may hold several space-delimited signatures during secret rotation — accept the delivery if any one verifies.
Easiest path: use an official Standard Webhooks library — npm install standardwebhooks or pip install standardwebhooks. Pass the raw body and headers to wh.verify(body, headers) and it checks the signature and the ±5 min replay window for you. The snippets below are the equivalent manual verification if you'd rather not add a dependency.
Sample Payload
All webhook payloads follow this structure. The data object varies by event type.
{
"id": "msg_7f3a9c12-0b4e-4d8f-a1c2-3e5f7a9b0d1e",
"type": "envelope.completed",
"timestamp": "2026-06-07T12:00:00.000Z",
"data": {
"envelope_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"template_id": "nda-simple",
"template_name": "Non-Disclosure Agreement",
"status": "completed",
"completed_at": "2026-06-07T12:00:00.000Z",
"signers": [
{
"id": "sgr_9b0d1e3e5f7a",
"email": "signer@example.com",
"name": "Jane Doe",
"status": "signed"
}
]
}
}Verify Signature
Paste your webhook secret, the webhook-id and webhook-timestamp headers, and the raw request body to compute the expected Standard Webhooks signature.