All help topics
Integrations and developersBusiness and up

Set up webhooks and replay deliveries

Register an https endpoint, subscribe it to document events, verify the signature header, and replay any delivery from the log without touching your data.

Updated Open in app

A webhook tells your own server that a document moved, without you polling for it. Open Settings > Developer > Webhooks, click Add endpoint, give it an https URL and the events you want, then copy the signing secret from the dialog that follows. Webhooks are part of the Developer section, available on Business and Ultimate, and admin-only.

Register a webhook endpoint

  1. Open Settings > Developer > Webhooks and click Add endpoint.

    The webhooks tab with the signature header note and the Add endpoint button

  2. Enter the Endpoint URL. It has to start with https. A signed payload sent in clear text still exposes document titles and signer email addresses, which is why plain http is refused.

  3. Choose a Mode. Test endpoints receive sandbox documents only and live endpoints receive real ones. The two streams never cross.

  4. Tick the Events you want. All seven start ticked, so untick what you don't need.

    The add webhook endpoint dialog with the URL field, mode select and event checkboxes

  5. Click Add endpoint, then copy the signing secret from the Copy your signing secret dialog before you close it. It's shown once and nothing can reveal it again.

You can hold five endpoints per mode.

The events you can subscribe to

EventFires when
document.sentSent to the first recipient
recipient.viewedA signer opened the document
recipient.signedA signer finished their fields
document.completedAll recipients signed
document.declinedA signer declined
document.expiredThe signing window closed
document.cancelledThe sender cancelled it

Each delivery is a JSON body with a stable envelope:

json
{
  "id": "evt_...",
  "event": "document.completed",
  "mode": "LIVE",
  "occurred_at": "2026-09-08T09:31:04.882Z",
  "document": {
    "id": "doc_...",
    "status": "completed",
    "title": "Master Services Agreement",
    "signed_pdf": null,
    "certificate": null
  },
  "recipient": {
    "id": "rcp_...",
    "name": "Aarav Mehta",
    "email": "aarav@example.com",
    "status": "signed"
  }
}

The recipient block is present only on the events that concern one person. Two extra headers ride along on every request, x-esign-event and x-esign-event-id, which is handy if you route by header before parsing the body.

Verify the signature before trusting a delivery

Every request carries an X-Esign-Signature header shaped like t=1757323864,v1=<hex>. The v1 value is an HMAC-SHA256 over the timestamp, a full stop, and the raw request body, keyed with your signing secret.

Verify it against the raw bytes you received rather than a re-serialized object, or the hash won't match. Reject anything whose timestamp is more than 300 seconds away from now. That window is what stops a captured delivery being replayed at you weeks later.

Read the delivery log

Click an endpoint row to expand its log. The most recent 25 deliveries are listed in five columns:

  • Event is the event name. Click it to expand the exact payload we sent, plus a Your server replied block holding the first part of your response body.
  • Result is a green status code on success, or a red badge carrying the status code or the error text.
  • Attempt is which of the three tries this row was.
  • When is the local timestamp.
  • Actions holds the Replay button for that delivery.

The endpoint row itself carries the mode badge, the number of subscribed events, and a red failed in 24h count when deliveries have been going wrong.

Replay a delivery

Click Replay in the Actions column of any row. A toast confirms it's queued, and a new row appears in the log for the fresh attempt. The original row stays where it is.

Replay is safe on a working integration too, provided your handler treats the event id as an idempotency key. That's worth building in anyway, since a retried delivery has the same event id as the first attempt.

Delete an endpoint

Click Delete on the endpoint row and confirm in the Remove this endpoint? dialog, whose button reads Remove endpoint. That stops deliveries immediately and throws away the endpoint's delivery history along with it, so pull anything you want to keep out of the log first. The signing secret goes too, which is the only way to get a fresh one.

Embedded signing sessions fire exactly the same events, so an endpoint set up here also covers anything running through embedded signing.

If something goes wrong

  • The Add endpoint button is disabled in the dialog. The URL doesn't start with https, or every event checkbox is unticked.
  • Deliveries fail with a timeout. Your handler took longer than ten seconds. Acknowledge with a 2xx first and do the slow work afterwards.
  • Signature checks keep failing. Something between us and your code is re-encoding the body. Hash the raw request bytes, before any JSON parsing.
  • The endpoint stopped receiving anything. Twenty consecutive failures parks it. Fix the server, remove the endpoint, and add it again.
  • You're seeing no deliveries at all. Check the mode. A test key's documents never reach a live endpoint, and a live key never reaches a test one.
FAQ

Frequently asked questions

How many times will a failed delivery be retried?

Three attempts in total, with an exponential wait that starts at five seconds. Each attempt gets ten seconds to respond before it is treated as a timeout, and every attempt is written to the log whether it succeeded or not, with its attempt number in its own column.

What happens if my endpoint stays down for days?

After twenty consecutive failed deliveries the endpoint is parked and stops receiving events. Delete it and register the URL again once your server is healthy. The red badge counting failures in the last 24 hours is your warning long before it gets that far.

Does a replay send fresh data or the original payload?

The original, byte for byte. Replaying re-sends exactly what was delivered at the time; it does not rebuild the payload from the document as it stands now. That is what you want when you are debugging why your handler rejected one particular body.

Can one endpoint receive both test and live events?

No. An endpoint is created in one mode and only ever receives documents from that mode. Register two endpoints if you want both streams, and count them separately against the limit, since the cap of five applies to each mode on its own.

I lost the signing secret. What now?

It is shown once at creation and stored encrypted afterwards, so nothing can print it again. Delete the endpoint and add it back to get a fresh secret. Deleting also throws away that endpoint's delivery history, so export any payloads you still need before you confirm.

Related

Keep going

Did not find what you needed?Send us a message