E-signature webhooks explained: events and retries
A webhook is how an e-signature platform tells your application that something happened — a signer completed a document, a request finished — without you having to repeatedly ask "is it done yet?" Instead of polling an endpoint on a schedule, you register a URL on your own server, and the platform sends an HTTP request to it when a relevant event occurs. This article covers how that works in general, what Esignapi specifically sends, and an important limitation worth planning around before you depend on webhooks as your only source of truth.
Why webhooks instead of polling
Polling — repeatedly calling an endpoint to check a request's status — works, but it's inefficient and introduces a delay between when something actually happens and when you find out. A webhook flips that: the platform notifies you the moment the event occurs, which is both faster and lighter on both sides than constant polling.
What a webhook delivery looks like
When a subscribed event occurs, Esignapi sends an HTTP POST request to the URL you've registered, with a JSON body describing the event, and three headers alongside it: a signature header for verifying the payload came from Esignapi, an event-type header naming what happened, and a timestamp header. Your endpoint should respond quickly with a success status once it's received the payload — the heavy lifting (updating your own database, triggering a follow-up action) can happen after you've acknowledged receipt.
Verifying the signature
Every webhook payload is signed using HMAC-SHA256 with a secret unique to your webhook configuration. Your endpoint should recompute the signature from the raw payload and your webhook secret, and compare it against the signature header included in the request, before trusting the payload's contents. This is what prevents someone else from sending a fake "signature.completed" request to your endpoint and having your system act on it as if it were genuine.
Which events Esignapi actually sends
This is worth being precise about, since a webhook settings page can list more subscribable event types than a platform reliably fires in practice — it's worth confirming this for whatever platform you're integrating with, not just assuming the full list in the UI is dispatched end to end. For Esignapi specifically, the events that are actually triggered from the signing flow are the completion of an individual signer's part, and the completion of the entire request once every required signer has finished. Before building logic that depends on a webhook firing at some other point in a document's lifecycle — such as when it's first opened, or when it expires — verify directly in the current documentation that event is actually dispatched, rather than assuming it based on what's offered as a selectable option when configuring a webhook.
Webhook delivery isn't automatically retried
This is the most important practical limitation to plan around: if your endpoint is down, times out, or returns an error when Esignapi attempts delivery, that delivery isn't automatically retried later. A single delivery attempt is made per event. This isn't unique to Esignapi — not every platform in this space guarantees retries — but it means you shouldn't treat webhooks as a guaranteed-delivery system on their own.
How to design around that limitation
- Keep your webhook endpoint fast and simple. Acknowledge receipt immediately, and do slower processing (database writes, triggering emails) asynchronously after responding, so a slow downstream step doesn't cause your endpoint to time out and miss a delivery.
- Reconcile periodically instead of relying on webhooks alone. A scheduled check that queries the status of requests you're still waiting on catches anything a missed webhook would otherwise have left out of sync.
- Log every webhook you receive, even ones your processing logic ends up ignoring, so you have a record to compare against if you ever suspect a delivery was missed.
See Error handling and idempotency in e-signature APIs for more on building a resilient integration around this kind of asynchronous event.
Designing your endpoint to handle duplicate or out-of-order events gracefully
Even without automatic retries, it's good practice to make your webhook handler tolerant of receiving the same event more than once, or events arriving slightly out of the order they occurred — for example, by checking whether you've already processed a given signature request's completion before acting on it a second time. This kind of defensive handling costs little to build and protects against edge cases in your own infrastructure (a duplicate queue message, a reprocessed log) as much as anything on the sending side.
Testing your webhook endpoint
Before relying on a webhook endpoint in production, send yourself a real test document and complete it as a signer, then confirm the webhook actually arrives and your endpoint processes it correctly — including checking your server logs if it doesn't show up as expected. A local tunnel tool that exposes your development server to the internet is the usual way to test a webhook endpoint before it's deployed anywhere publicly reachable.
Where webhook configuration lives
Webhooks are configured per developer account, with each webhook entry specifying a destination URL and which event types it should receive. A single account can register more than one webhook URL if different parts of your own infrastructure need to react to events independently, rather than funneling everything through one endpoint and routing internally.
What a typical webhook payload contains
Beyond the event name, the JSON body of a webhook delivery includes the data relevant to that event — for a signer completion, that typically means identifying which signature request and which signer the event relates to, so your handler can look up the corresponding record in your own system without needing to make a separate API call just to figure out what happened. Combined with the timestamp header, this gives your handler everything it usually needs to update its own state without an additional round trip back to the API.
Why acknowledging quickly matters more than it might seem
An HTTP request that takes a long time to receive a response is a common source of flaky-seeming integrations, not because anything is actually broken, but because a slow endpoint response can look indistinguishable from a failed delivery if your own monitoring isn't specific about the difference. Structuring your webhook handler to do the minimum necessary work synchronously (verify the signature, record that the event arrived) before kicking off anything slower asynchronously keeps your endpoint fast and your monitoring signal clean.
Set up your webhook
Esignapi's documentation covers how to register a webhook URL, select events, and verify the HMAC-SHA256 signature in the language of your choice.
Frequently asked questions
What happens if my server is down when a webhook would have been sent?
The delivery attempt happens once; if your endpoint doesn't respond successfully at that moment, it isn't automatically retried later. This is exactly why a periodic reconciliation check, rather than webhooks alone, is the safer design for anything where missing an event would actually matter.
How do I verify a webhook actually came from Esignapi and not an attacker?
Recompute the HMAC-SHA256 signature from the raw request body using your webhook secret, and compare it to the signature header sent with the request. If they don't match, reject the payload.
Can I subscribe to multiple events with one webhook URL?
Yes, a single webhook endpoint can be configured to receive more than one event type, with the specific event named in the payload and in a header so your handler can branch on it.
Should I respond to the webhook before or after processing it?
Generally before — acknowledge receipt with a quick success response, and do any slower processing afterward, so a delay in your own downstream logic doesn't risk the delivery attempt timing out.
Is there a way to see a history of webhook deliveries I've received?
Logging every webhook payload you receive on your own end is the most reliable way to keep that history, since that record is the one you'll want to compare against if you ever need to investigate a gap.