DocuSign Connect Webhooks: Events, HMAC and Retry Behavior

A practical guide to DocuSign Connect webhooks: envelope and recipient events, the JSON payload, HMAC signature verification, and what Connect's aggressive retries mean for your listener.

DocuSign Connect webhooks

When an envelope is signed, declined or completed, DocuSign Connect is the machinery that tells your application — a webhook POST with the envelope state as JSON. Connect is more configurable than most providers' webhooks (account-wide vs per-envelope, event filtering, includes), and it has one behavior that surprises everyone the first time: it retries hard. We run a public webhook bin and routinely watch DocuSign hitting long-dead endpoints with retryCount in the twenties. This guide covers setup, events, payloads, HMAC verification, and how to build a listener that survives all of that.

Two ways to get events

Account-level Connect configuration. In eSignature admin: Settings → Connect → Add configuration. You set the listener URL, pick events, and every matching envelope in the account triggers a delivery. This is the right choice for CRM syncs, archives, and anything ongoing.

Per-envelope eventNotification. When creating an envelope via the API, attach an eventNotification object with your URL and the events you want — scoped to that envelope only. Right for multi-tenant apps where each envelope may notify a different customer system.

Both deliver the same JSON format (use the modern JSON (REST v2.1) format; the legacy XML format still exists in old configurations).

The events

The two families you will subscribe to:

  • Envelope events: envelope-sent, envelope-delivered, envelope-completed, envelope-declined, envelope-voided
  • Recipient events: recipient-sent, recipient-delivered, recipient-completed, recipient-declined, recipient-authenticationfailed, and more

For a typical "do something when the document is fully signed" integration, envelope-completed alone is enough — recipient events are for tracking individual signers through the flow.

The payload

A JSON delivery looks like this (trimmed):

{
  "event": "envelope-completed",
  "apiVersion": "v2.1",
  "uri": "/restapi/v2.1/accounts/{accountId}/envelopes/{envelopeId}",
  "retryCount": 0,
  "configurationId": 10000001,
  "generatedDateTime": "2026-01-15T10:30:00.0000000Z",
  "data": {
    "accountId": "a1b2c3d4-…",
    "envelopeId": "e5f6a7b8-…",
    "envelopeSummary": {
      "status": "completed",
      "emailSubject": "Please sign: Services Agreement",
      "recipients": { "signers": [{ "name": "Alex Doe", "status": "completed" }] }
    }
  }
}

Notes from real traffic:

  • retryCount is your friend. Zero means first attempt; anything higher means DocuSign already tried and failed. Use it together with data.envelopeId for idempotency.
  • Enable include options (documents, certificate of completion) only if you need them — payloads grow from a few KB to whole signed PDFs base64-encoded inline.
  • The Webhook Bin sample catalog includes real-shaped recipient-delivered and envelope-completed events you can POST at your handler with one click.

Verify the HMAC signature

Connect deliveries are unsigned by default — you must enable HMAC on the configuration and store the generated key (DocuSign shows it once). After that, every delivery carries:

X-DocuSign-Signature-1: Base64(HMAC-SHA256(raw_body, key))

Additional active keys arrive as X-DocuSign-Signature-2, -3, … (up to 100), which is how you rotate keys with zero downtime — verify against each active key and accept on any match. Test your implementation interactively with our free DocuSign webhook signature verifier, and read Verify a webhook signature for the general pitfalls (raw bytes, constant-time comparison).

Listener best practices — designed around the retries

DocuSign's delivery contract: answer 2xx within 100 seconds or the delivery counts as failed and enters the retry queue (roughly 24 hours of attempts at growing intervals). That, plus what we observe in the wild (20+ retries against dead endpoints), dictates the architecture:

  1. Acknowledge fast, process later. Persist the raw delivery to a queue and return 200 immediately. Never do the PDF download or the CRM write inline.
  2. Be idempotent. Key on envelopeId + event + status; retries and out-of-order deliveries both happen.
  3. Do not trust event ordering. A recipient-completed retry can arrive after the envelope-completed that logically follows it. Treat each event as "fetch current state if in doubt" — the uri field gives you the exact API path.
  4. Keep the endpoint stable. Every URL change re-enters the config UI. A stable relay endpoint in front (with storage and up to 30 days of retries towards your side) decouples DocuSign's configuration from your infrastructure — deploys and outages on your end stop being delivery failures DocuSign has to retry.

Local development

DocuSign only POSTs to public HTTPS URLs. For the dev loop — inspect the payload in a Webhook Bin, then forward live events to localhost with the relay agent — follow Test DocuSign webhooks locally.