REFERENCE

Webhooks reference

Create and delete endpoints, list them, read the delivery log, and replay a delivery.

All documentation

Five endpoints for managing endpoints and inspecting what was delivered. For the payload shape, the signature routine and the retry policy, read the webhooks guide.

POST/v1/webhooks
Requires webhooks:write
Body
FieldTypeNotes
urlstringrequiredMust start with https://. Up to 2000 chars.
eventsstring[]requiredAt least one of the seven event types.
bash
curl https://api.documentesign.com/v1/webhooks \
  -H "Authorization: Bearer $ESIGN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/hooks/esign",
    "events": ["document.completed", "document.declined"]
  }'
201 Created
{
  "id": "whk_2f8d...",
  "url": "https://api.example.com/hooks/esign",
  "mode": "LIVE",
  "events": ["document.completed", "document.declined"],
  "status": "ACTIVE",
  "created_at": "2026-09-01T10:00:00.000Z",
  "signing_secret": "whsec_..."
}
signing_secret appears here and nowhere else
It is returned once, on create, then stored encrypted. Save it immediately. Recovering from a lost secret means deleting the endpoint and creating a new one.

The endpoint inherits the mode of the key that created it and cannot be moved between modes. Five endpoints per mode; exceeding that returns 402 webhook_endpoint_limit_reached with the ceiling in cap.

GET/v1/webhooks
Requires webhooks:read

No parameters. Returns only endpoints in your key's mode, newest first. signing_secret is not included.

200 OK
{ "data": [ { "id": "whk_2f8d...", "url": "https://...",
             "mode": "LIVE", "events": ["document.completed"],
             "status": "ACTIVE", "created_at": "..." } ] }

A status of DISABLED means the last twenty deliveries all failed and we stopped trying. Deliveries are dropped while an endpoint is disabled, so check here first if events went quiet.

DELETE/v1/webhooks/{id}
Requires webhooks:write
200 OK
{ "id": "whk_2f8d...", "deleted": true }

This is permanent, and it takes the delivery history with it.

GET/v1/webhooks/{id}/deliveries
Requires webhooks:read
Query parameters
FieldTypeNotes
limitinteger1 to 100. Defaults to 20. No cursor on this endpoint.
200 OK
{
  "data": [
    { "id": "dlv_5b3c...",
      "event": "document.completed",
      "event_id": "evt_doc7a1b_document.completed_doc",
      "document_id": "doc_7a1b...",
      "attempt": 1,
      "response_status": 500,
      "response_body": "Internal Server Error",
      "error": null,
      "succeeded": false,
      "payload": { },
      "created_at": "2026-09-01T10:41:02.000Z" }
  ]
}

Every attempt is recorded, successful or not, so a failing receiver leaves a trail. response_body holds up to 2000 characters of what you returned, which is usually enough to see the exception.

POST/v1/webhooks/{id}/deliveries/{deliveryId}/replay
Requires webhooks:write
200 OK
{ "replayed": true, "event_id": "evt_doc7a1b_document.completed_doc" }

Re-sends the original stored payload rather than rebuilding it, so what arrives is byte-identical to the first attempt and the signature covers the same content. Replays are never deduplicated against the delivery they came from, so this always produces a fresh attempt.

Errors
FieldTypeNotes
webhook_endpoint_not_found404Unknown id, another workspace, or an endpoint in the other mode.
delivery_not_found404The delivery belongs to a different endpoint.
webhook_endpoint_limit_reached402Five per mode. Carries cap.