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.
/v1/webhooks| Field | Type | Notes |
|---|---|---|
url | stringrequired | Must start with https://. Up to 2000 chars. |
events | string[]required | At least one of the seven event types. |
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"]
}'{
"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_..."
}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.
/v1/webhooksNo parameters. Returns only endpoints in your key's mode, newest first. signing_secret is not included.
{ "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.
/v1/webhooks/{id}{ "id": "whk_2f8d...", "deleted": true }This is permanent, and it takes the delivery history with it.
/v1/webhooks/{id}/deliveries| Field | Type | Notes |
|---|---|---|
limit | integer | 1 to 100. Defaults to 20. No cursor on this endpoint. |
{
"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.
/v1/webhooks/{id}/deliveries/{deliveryId}/replay{ "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.
| Field | Type | Notes |
|---|---|---|
webhook_endpoint_not_found | 404 | Unknown id, another workspace, or an endpoint in the other mode. |
delivery_not_found | 404 | The delivery belongs to a different endpoint. |
webhook_endpoint_limit_reached | 402 | Five per mode. Carries cap. |