Developer first webhooks: 3 tests for digital signature APIs

Yes, modern digital signature APIs include webhooks as a standard feature. The real question isn't whether webhooks exist. It's whether the provider's webhook implementation is reliable enough to build production workflows on. Evaluate any digital signature API with webhook support on three axes: event coverage, verification method, and retry semantics. Before you commit, run a sandbox test and confirm you can verify raw-body signatures without friction.
TL;DR:
- Webhook reliability and event coverage are critical, as poor implementation can cause loss of sign-triggered events, security issues, and automation failures.
- Expect providers to offer both per-recipient and envelope-level events in JSON format, with stable schemas and clear documentation, to support flexible automation workflows.
- Verify webhook authenticity using HMAC signatures over raw request bodies or public-key signatures, with timestamp checks and HTTPS to prevent malicious triggers.
- Design your receiver to process events idempotently, store delivery IDs for deduplication, and return immediate 200 responses after queuing events to handle retries gracefully.
- Use sandbox testing with replay capabilities and SDK examples to confirm your setup works securely and reliably before deploying to production.
Table of Contents
- Why webhook quality matters for production e-signature integrations
- What events, payloads, and schemas should you expect?
- How do you verify a webhook is authentic?
- How should you handle retries and avoid duplicate processing?
- How do you test webhooks before going live?
- What does a production-ready receiver look like?
- Common pitfalls and how to troubleshoot them
- How do webhook capabilities compare across providers?
- What legal and compliance factors apply to webhook data?
- Webhook-first integration vs polling: the Formable view
- Add embedded signing with reliable webhooks in your product
- Sources
- FAQ
Why webhook quality matters for production e-signature integrations
Webhooks are how your application finds out that someone signed, viewed, or declined a document without you polling an endpoint every few seconds. That sounds simple. In practice, the quality of a provider's webhook system determines how much engineering debt you inherit six months into a production integration.
A poorly designed webhook feed creates three specific failure modes. First, events get lost or arrive malformed, which means your database silently drifts out of sync with the actual signing status. Second, payloads that can't be verified force you to either trust unauthenticated data (a security problem) or build workarounds that call back to the API for confirmation (a performance problem). Third, inconsistent event granularity, where one provider fires an event per recipient and another only fires one event when the entire envelope closes, breaks automation that assumes one behavior or the other.
These aren't abstract engineering concerns. They show up as business problems fast:
- Sales deals stall because a signed contract's status never updates in your CRM.
- Legal or ops teams do duplicate manual checks because they've stopped trusting the automated status.
- Audit trails become inconsistent, which is a real problem if a regulator or counterparty later asks for proof of when a signature happened.
- Support tickets pile up from customers who signed but see their status as "pending."
Webhook design is also where you can tell how much a provider actually thinks about developer experience. A signature API with webhooks worth building on will document every event type, publish a stable payload schema, and give you tools to test before you ship. One that treats webhooks as an afterthought usually shows it in the documentation gaps first: missing retry details, no mention of signature verification, and payload examples that don't match what actually arrives.
What events, payloads, and schemas should you expect?
Digital signature APIs generally emit two categories of webhook events: per-recipient events and envelope-level events. Per-recipient events fire for each signer's individual action (viewed, signed, declined), which matters if your workflow needs to track progress signer by signer, like sending targeted reminders to whichever party hasn't acted yet. Envelope-level events fire once for the entire document or agreement (completed, voided, expired), which is enough if all you care about is the final outcome.
Most integrations end up needing both. A common event taxonomy looks like this:
recipient.viewed— a specific signer opened the documentrecipient.signed— a specific signer completed their signaturerecipient.declined— a specific signer refused to signenvelope.completed— every required signer has signedenvelope.voided— the document was canceled before completion
Legalesign's webhook documentation illustrates this pattern well, using event names like document.completed and recipient.completed alongside both HMAC and public-key verification options.
On payload format, JSON has become the practical default across the industry, and for good reason. It parses natively in JavaScript, has mature libraries in Python, Java, Go, and every other backend language, and plays well with the SDKs most providers ship. XML still shows up in older enterprise systems, but unless you're integrating with a legacy platform that requires it, JSON payloads will save you real development time.
Schema stability matters more than most teams plan for. Providers add new fields to webhook payloads regularly as they ship features. Your integration should read fields by name and ignore unrecognized ones, rather than validating against a strict fixed schema that breaks the moment the provider adds something new. Treat the presence of a documented field, like event_type, envelope_id, or timestamp, as the stable contract, and everything else as additive.
One detail worth internalizing: providers that separate per-signer events from envelope-level events give you meaningfully more flexibility in downstream automation than providers offering only a single completion event, because you can react to partial progress instead of waiting for everything to finish.
How do you verify a webhook is authentic?
An unverified webhook is just an HTTP request from the internet claiming to be your signature provider. Anyone who guesses or leaks your endpoint URL could send a fake "document signed" event and trigger downstream automation, like releasing funds or activating a contract, that never should have fired. Verification closes that gap, and there are two dominant approaches.
- HMAC verification. The provider signs the payload with a shared secret and sends the resulting hash in a header. Your receiver recomputes the HMAC using the raw request body (not the parsed JSON object, which can reorder keys or alter whitespace) and compares it to the header value using a constant-time comparison function, not a simple string equality check, to avoid timing attacks.
- Public-key (asymmetric) signatures. The provider signs with a private key and publishes the corresponding public key. Your receiver verifies the signature against that public key. This approach avoids sharing a secret at all, which some security teams prefer, though it adds key rotation and key-distribution overhead on your end.
Timestamp checks add a second layer of protection against replay attacks. Most webhook systems include a timestamp header alongside the signature. Reject any request where the timestamp falls outside a defined window, commonly five minutes, since a captured and replayed request will arrive with a stale timestamp even if the signature itself is technically valid.
Beyond verification logic, endpoint hardening still matters. Serve your webhook endpoint over HTTPS only, restrict the endpoint's permissions to exactly what processing the event requires, and apply rate limiting so the endpoint can't be used as an attack surface even if verification is bypassed somehow. Guidance on protecting web-facing forms from abuse applies directly here, since a webhook receiver is functionally a public form endpoint that happens to accept JSON instead of form fields.
Pro Tip: Grab the raw request body before any framework middleware parses it into a JSON object. Most HMAC verification bugs come from computing the hash over a re-serialized version of the payload, which almost never matches the original bytes the provider signed.
How should you handle retries and avoid duplicate processing?
Providers don't fire a webhook once and hope. When your endpoint returns anything other than a success status, most systems retry on an exponential backoff schedule, often over several attempts spread across minutes or hours, before giving up and, in better implementations, routing the failed event to a dead-letter queue you can inspect later.
That retry behavior is a feature, not a bug, but it means your receiver will occasionally get the same event twice. Design for it from day one:
- Extract the provider's delivery ID or event ID from every payload and check it against a dedupe store before processing.
- Use idempotency keys on any downstream action the webhook triggers, like updating a contract's status, so a duplicate delivery is a no-op rather than a duplicate charge or duplicate email.
- Keep the dedupe window generous. A few hours is usually enough to cover retry storms without holding unlimited state.
- Return a
200response the moment you've durably queued the event for processing, not after your full business logic finishes, so the provider doesn't retry a request that actually succeeded but took too long to answer.
Observability closes the loop. Log every webhook received, including the ones you reject during verification, and put a dashboard or alert on delivery failures. If your rejection rate suddenly spikes, that's usually a sign the provider rotated a signing secret, changed a header format, or you deployed a bug, and you want to know that within minutes, not when a customer complains their contract never updated.
Pro Tip: Set an alert specifically on "zero webhooks received in the last hour" during business hours, not just on error rates. A silent integration that's stopped receiving events entirely is often more dangerous than one throwing visible errors, because nothing looks broken until someone notices stale data days later.
How do you test webhooks before going live?
The single best predictor of a smooth production rollout is whether you can fully exercise the webhook flow before real signers are involved. Look for a provider that gives you sandbox API keys and the ability to fire test or replay events on demand, rather than forcing you to complete an actual signing flow every time you want to test your receiver code.
A practical testing sequence looks like this:
- Stand up your receiver locally, using a tunneling tool like ngrok or a temporary serverless endpoint, so the provider's sandbox can reach your machine during development.
- Register that temporary URL with the provider's sandbox and trigger a test event, such as a simulated
recipient.signedevent, to confirm your endpoint receives it at all. - Verify signature checking against the sandbox's test secret or test key pair, deliberately including at least one deliberately-broken payload to confirm your rejection logic actually rejects it.
- Move your receiver to a real cloud environment. Azure Functions and comparable serverless platforms are common choices here, since they let you deploy an HTTP-triggered function quickly and iterate without managing a full server.
- Replay production-shaped test events against the deployed endpoint before switching any real traffic over, confirming logging, dedupe, and alerting all fire correctly.
The providers worth prioritizing are the ones that pair this workflow with a Postman collection, an SDK with built-in verification helpers, and raw-body code examples in more than one language. That combination tells you the provider's own engineers use the webhook system daily, rather than having bolted it on to satisfy a feature checklist. For a deeper walkthrough of receiver code, a Node.js integration guide or Python integration guide will save you from reinventing verification logic that's already been solved.
What does a production-ready receiver look like?
Strip away the specifics of any one provider, and every solid webhook receiver follows the same shape: capture the raw request body, verify the signature against that raw body, enqueue the event for asynchronous processing, and return a 200 immediately. Everything else, updating your database, notifying a user, triggering the next workflow step, happens after that acknowledgment, off the request thread.
Before flipping a webhook integration into production, run through this checklist:
- TLS only, no plain HTTP endpoint ever accepted, even temporarily.
- Signature verification enforced on every request, with no fallback path that skips it.
- A dedupe store keyed on delivery ID to absorb retries without double-processing.
- Metrics and alerts on delivery volume, verification failures, and processing latency.
- A dead-letter path for events that fail processing repeatedly, so nothing silently vanishes.
One decision that trips up a surprising number of teams: whether to rely on the signed document data included in the webhook payload, or to make a separate API call back to fetch the signed PDF and full audit trail. Webhook payloads are usually metadata-only, event type, envelope ID, timestamp, and recipient status, not the full signed artifact. If your workflow needs the actual signed document, plan for a follow-up API call triggered by the completion event rather than assuming the file arrives in the webhook itself. This consolidated approach to endpoint security, covering HTTPS, timestamp tolerance, constant-time comparison, and fast acknowledgment, reflects what most mature webhook implementations converge on independently of which provider you choose.
Common pitfalls and how to troubleshoot them
Most webhook integration problems trace back to a small set of recurring mistakes, and recognizing them early saves days of debugging.
Verifying against parsed JSON instead of the raw body is the most common bug. Frameworks like Express or Flask parse the request body automatically before your handler code runs, and by the time you access it, whitespace and key order may have changed just enough to break the HMAC comparison. Configure your framework to expose the raw body specifically for the webhook route.
Treating a missing event as "nothing happened" is a close second. If your integration silently assumes no news is good news, a dropped event during a provider outage becomes an invisible bug. Reconcile periodically: query the API directly for envelope status on any contract that hasn't received a completion webhook within an expected window, and flag the mismatch.
Ignoring header case sensitivity and encoding trips up teams migrating between languages or frameworks, since some HTTP libraries lowercase headers automatically and others don't. Test your header-reading code against the exact casing the provider documents, not just what happens to work in local testing.
Assuming test and production secrets are interchangeable causes signature verification to fail mysteriously the day you go live. Keep sandbox and production credentials clearly separated in your configuration, and confirm which one is active before debugging anything else.
When a webhook integration breaks, check these four things in order: is the endpoint reachable, is the signature verification using the raw body, is the secret or key the current one, and has the provider's schema changed recently. That order resolves the overwhelming majority of real-world incidents.

How do webhook capabilities compare across providers?
Webhook implementations vary less in whether they exist and more in how much operational detail they expose to developers. When evaluating a digital signature API with webhook support, compare providers against consistent criteria rather than a feature checklist that just confirms webhooks are present.
| Evaluation criterion | What to look for |
|---|---|
| Event granularity | Per-recipient events available, not just envelope-level completion |
| Verification method | HMAC and/or public-key signatures, clearly documented with code samples |
| Retry policy | Documented backoff schedule, maximum attempts, and dead-letter handling |
| Sandbox testing | Ability to trigger test/replay events without a real signing flow |
| SDK and code examples | Raw-body verification examples in more than one language |
| Payload format | JSON as the default, with a documented and versioned schema |
Enterprise-oriented providers like Adobe's Acrobat Sign document a full set of webhook concepts, including endpoint registration, event subscriptions, and verification options, which is a reasonable baseline to measure any newer entrant against. Smaller or API-first providers sometimes differentiate by making sandbox replay and raw-body examples easier to find, since that's often the deciding factor for a developer choosing between two otherwise similar feature sets.
The comparison that actually matters isn't a table of checkmarks. It's whether you can get a verified test event flowing end to end in an afternoon, or whether you're still parsing documentation three days later.
What legal and compliance factors apply to webhook data?
Webhook payloads for e-signature events typically carry personal data: signer names, email addresses, IP addresses, timestamps, and sometimes document metadata that reveals the nature of the underlying agreement. That makes your webhook receiver part of your compliance surface, not just your engineering surface.
Under U.S. law, the enforceability of the underlying electronic signature rests on the E-SIGN Act, codified at 15 U.S.C. § 7001, which confirms that electronic signatures satisfy signature requirements for most transactions when all parties have consented to do business electronically. That statute governs signature validity, but it doesn't specifically regulate how webhook data must be transmitted or stored, so your data-handling obligations come from wherever your business already sits: state privacy law, sector-specific rules if you're in healthcare or finance, and any contractual data-processing terms you've signed with customers.
Practical compliance steps worth building into your receiver: avoid logging full payloads in plaintext if they contain personal data, encrypt data at rest wherever you persist webhook contents, and set a retention policy so old event logs don't accumulate indefinitely. If your customers operate in regulated industries, confirm whether your signature provider offers a data processing agreement, since that document, not the webhook payload format itself, is usually what a customer's legal or compliance team will ask for first.
Webhook-first integration vs polling: the Formable view
Event-driven architecture wins for contract workflows because latency and cost both compound. Polling an API every few minutes to check signature status means paying for API calls that return "nothing changed" the vast majority of the time, and it means your CRM or deal pipeline updates in minutes instead of seconds. For a sales team watching a deal close, that lag is the difference between a smooth handoff and a customer wondering why their signed contract hasn't triggered the next step.
Polling still has a place. If you're integrating in a locked-down network that can't expose an inbound webhook endpoint, or you're building a low-volume internal tool where a five-minute delay genuinely doesn't matter, polling is simpler to reason about and easier to secure. Don't default to it just because webhooks feel like more upfront work.
The teams that get this right treat webhook verification as a one-time investment, not a recurring cost. Build it once, correctly, and every future integration into that signing flow inherits it for free.
— Alex
Add embedded signing with reliable webhooks in your product
There are providers that give developers a full embedded signing API with webhook delivery built to a high standard including documented event types, signature verification, and sandbox testing before production use.

Some platforms handle contract workflows comprehensively, with tools that support negotiation through redlining and AI-assisted contract review to catch missing clauses and risks during intake, making signing part of an integrated workflow rather than just an isolated API call. That matters if you're building for sales, legal, or operations teams who need the contract lifecycle connected end to end, not just a signature captured.
If you're evaluating a digital signature API with webhook support for a production integration, start by testing Formable's sandbox environment against your own receiver code. Check the security and compliance details if your team needs to answer questions from legal or procurement, and explore the embedded signing documentation to see the webhook event structure firsthand.
Sources
- 15 U.S. Code § 7001 - General rule for electronic records and signatures
- Create your first function - Azure Functions | Microsoft Docs
- How to protect forms from online abuse | Moxy Web
- Acrobat Sign webhook overview
FAQ
Do digital signature APIs support webhooks by default?
Yes, most established digital signature APIs offer webhooks as a core feature, though the depth of event coverage, verification options, and documentation quality varies significantly between providers.
What's the best way to verify a webhook payload is genuine?
Compute an HMAC over the raw, unparsed request body using the shared secret the provider gives you, then compare it to the signature header using a constant-time comparison function rather than a standard equality check.
How many times will a provider retry a failed webhook delivery?
Retry schedules vary by provider, but most use exponential backoff with multiple attempts before marking the delivery as failed, so your receiver should always be idempotent to handle duplicate deliveries safely.
Should I use per-recipient or envelope-level webhook events?
Use per-recipient events if you need to track individual signer progress, like sending targeted reminders, and envelope-level events if you only care about the final completion or void status of the entire document.
Does Formable offer webhooks for e-signature events?
Yes, Formable's embedded signing API includes webhook delivery with signature verification and sandbox testing, built for developers integrating e-signatures directly into their own product workflows.
Is JSON or XML the better webhook payload format?
JSON is the practical standard for webhook payloads today, since it parses natively across modern languages and integrates cleanly with most provider SDKs, while XML mainly persists in legacy enterprise systems.




