Events
Webhook events
Register an endpoint with POST /v1/webhooks (an
https:// URL and an optional list of event types; an empty
list subscribes to everything). Each delivery is a POST with
a JSON body and the headers below.
Event types
| Type | When |
|---|---|
document.approved | An approver approved the document. An approval is not a signature. |
document.bounced | A signing email could not be delivered to a recipient. |
document.completed | Every recipient has signed. Sealing starts. |
document.created | An envelope was created (draft or finalized). |
document.expired | The envelope's expiry passed before every recipient signed. |
document.opened | A recipient opened their signing link for the first time. One event per recipient. |
document.rejected | A recipient declined, which closes the envelope. |
document.sealed | The sealed PDF, with its Certificate of Completion, is ready to download. |
document.sent | The envelope was initially sent and signing links were issued. Reminders and re-sends do not emit this event. |
document.signed | A signer completed all of their fields and signed. |
document.viewed | A viewer marked the document as viewed. A view is not a signature or an approval. |
Payload
{
"id": "evt_outbox_1234",
"type": "document.signed",
"created_at": "2026-08-22T12:00:00+00:00",
"document": "doc_...",
"mode": "live",
"data": {
"seq": 4,
"engine_event_type": "recipient_completed",
"actor": {
"type": "recipient",
"id": "3f1c…",
"email": "ada@example.com"
}
}
}
id | Unique per event, stable across redeliveries. Use it to deduplicate. |
|---|---|
type | One of the types above. |
created_at | When the event happened, ISO 8601 UTC. |
document | The envelope id, as returned by the API. |
mode | live or test. Endpoints are workspace-level and receive both; a handler that must ignore test traffic checks this member. |
data | The audit-trail event behind this type: its sequence number in the envelope's chain, the engine event name, and the actor. |
document.signed, document.approved and
document.viewed share this shape and the engine event
recipient_completed; the type says which act it was. A
recipient with the approver role approves, and an approval is
not a signature, so it never produces document.signed. A
recipient with the viewer role marks the document as viewed,
which is neither, so it produces document.viewed. An endpoint
that lists event types needs document.approved and
document.viewed in its list to hear approvals and views.
document.opened still means a link was opened, by anyone.
{
"id": "evt_outbox_1235",
"type": "document.approved",
"created_at": "2026-08-22T12:05:00+00:00",
"document": "doc_...",
"mode": "live",
"data": {
"seq": 7,
"engine_event_type": "recipient_completed",
"actor": {
"type": "recipient",
"id": "8a2d…",
"email": "grace@example.com"
}
}
}
Test pings
POST /v1/webhooks/{id}/ping (or "Send a test ping" in the
dashboard) queues one delivery of type ping to that endpoint.
It is signed and retried like every other delivery, so it is the way to
check a handler end to end before any envelope exists. ping
is not an event type: it cannot be subscribed to, and an endpoint's event
filter does not apply to it. The body has no document or
data member.
{
"id": "evt_ping_3f9a1c2b7d4e8f01",
"type": "ping",
"created_at": "2026-08-23T12:00:00+00:00",
"mode": "live"
}
Headers
X-SignEnvoy-Event | The event type, repeated from the body (ping for a test ping). |
|---|---|
X-SignEnvoy-Signature | HMAC signature of the body; see verifying signatures. |
Content-Type | application/json |
User-Agent | SignEnvoy-Webhooks/1.0 |
Delivery and retries
A delivery succeeds on any 2xx response within
10 seconds. Anything else is retried
7 times, after 30 s, 5 min, 30 min, 2 h, 5 h, 10 h, 10 h:
about 28 hours from the first attempt to the last. After
8 attempts the delivery is marked dead.
Every attempt, retries and replays included, is signed at the moment
it is sent with a fresh t, so your handler can enforce a
timestamp tolerance; the payload and its id do not change.
Deliveries are not guaranteed to arrive in order; use created_at
and data.seq to order events for one envelope. The worker
sends at most 150 deliveries a minute to any one endpoint, so a
backlog arrives at that pace rather than all at once.
Every delivery is listed under GET /v1/webhooks/{id}/deliveries
(?status=dead is the dead-letter view), and
GET /v1/webhooks/{id}/deliveries/{delivery_id} returns
one with the payload as posted and a record of every attempt: when it
was sent, how long it took, the t it was signed with, the
status your endpoint returned and up to 4 KiB of its response
body. The dashboard's delivery page shows the same. Delivered and dead
deliveries, with their attempts, are kept for 30 days
after creation (a replay inside that window keeps them another
30); queued deliveries are never removed.
A dead or delivered delivery can be queued again with
POST /v1/webhooks/{id}/deliveries/{delivery_id}/redeliver.
To replay many at once, POST /v1/webhooks/{id}/deliveries/replay
with {"since": "2026-10-10T00:00:00Z", "status": "dead"}
(until is optional; "status": "all" includes
delivered ones) re-queues up to 1000 deliveries
created in the window, oldest first. A replay carries the same
id and a fresh signature, so a handler that deduplicates on
id is safe to point at it.
Disabled endpoints
A delivery to a disabled endpoint is not attempted and does not count
against the schedule: it waits, is looked at again every
30 minutes, and goes out when the endpoint is re-enabled
(PATCH /v1/webhooks/{id} with {"active": true},
or "Re-enable" in the dashboard). A delivery that has waited
7 days is marked dead, and can be replayed like any other.
No new deliveries are queued for a disabled endpoint.
If every delivery to an endpoint has failed for 3 days, or
if fewer than 5% of at least 50
attempts over the last 3 days succeeded, SignEnvoy disables
it, records the reason, and emails each workspace owner once. The endpoint's listing carries failing_since,
last_success_at, last_failure_at,
disabled_reason (auto) and
disabled_at, so an integration can watch its own health.
Re-enabling clears the markers and sends the waiting deliveries at once;
deliveries that went dead in the meantime can be replayed as above.