Webhooks
Autosignly POSTs a JSON body to the webhook URL configured for the API key when an asynchronous event happens. Subscribe to event names in the Autosignly application (API → Webhooks).
They are not endpoints of this API — you expose a receiver, Autosignly calls it. The same catalog (event types, payload schemas, signature headers) lives under Webhooks in the OpenAPI document.
Verifying a delivery
Every delivery is signed. Check the headers against the raw request body
before parsing JSON — re-serialising the body changes the bytes and the
signature will not match. The SDKs expose this as webhooks.verify (Python,
Node.js) or Webhooks.verify (Java) — and a non-throwing is_valid/isValid
counterpart in each.
- Read
X-Webhook-Timestamp(Unix seconds) andX-Webhook-Signature. - Compute
hex(HMAC-SHA256(webhook_key, timestamp + "." + raw_body)). - Accept when any comma-separated entry of
X-Webhook-Signatureequalsv1=<digest>(constant-time compare). Severalv1=signatures appear while the signing key is being rotated. - Reject when
|now - timestamp| > 300seconds (five minutes), even if the signature matches — that is the replay window.
Respond with any HTTP 2xx to acknowledge. Other statuses are retried.
from autosignly import webhooks
webhooks.verify(
request.body,
request.headers["X-Webhook-Signature"],
webhook_key,
request.headers["X-Webhook-Timestamp"],
)
Envelope
The HTTP body is always:
{
"eventId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"companyId": "7f3c1a2b-beef-4d5e-a6f7-123456789abc",
"eventType": "DOCUMENT_SIGNED",
"payload": {
"documentId": "03bef6df-faca-4aee-9836-80caeeaf4418",
"signerId": "7c2a1b4e-9d3f-4a12-8e5b-1f6c0a9d8e7b",
},
"companyApiId": "PROD"
}
eventId uniquely identifies the delivery — use it to ignore duplicates.
companyApiId is the environment id (PROD or a sandbox UUID).
email is omitted when the signer has no email.
Event types
eventType | When it is sent | payload |
|---|---|---|
DOCUMENT_SIGNED | A signer completed their signature. Further signers may still be pending. | { "documentId", "signerId", "email"? } |
DOCUMENT_ALL_SIGNATURES_DONE | Every required signature has been collected. | { "documentId" } |
DOCUMENT_CANCELLED | Signing ended without a complete set of signatures. | { "documentId", "cancellationReason", "signerId", "cancelledAt" } |
DOCUMENT_RESTORED | A previously cancelled document was restored and signing can continue. | { "documentId", "restoredAt" } |
cancellationReason is one of REJECTED_BY_SIGNER, EXPIRED, CANCELLED_BY_SENDER.
signerId is null when the sender cancelled the process. cancelledAt and
restoredAt are UTC instants (2026-09-10T11:00:00Z).