Skip to main content

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.

  1. Read X-Webhook-Timestamp (Unix seconds) and X-Webhook-Signature.
  2. Compute hex(HMAC-SHA256(webhook_key, timestamp + "." + raw_body)).
  3. Accept when any comma-separated entry of X-Webhook-Signature equals v1=<digest> (constant-time compare). Several v1= signatures appear while the signing key is being rotated.
  4. Reject when |now - timestamp| > 300 seconds (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",
"email": "[email protected]"
},
"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

eventTypeWhen it is sentpayload
DOCUMENT_SIGNEDA signer completed their signature. Further signers may still be pending.{ "documentId", "signerId", "email"? }
DOCUMENT_ALL_SIGNATURES_DONEEvery required signature has been collected.{ "documentId" }
DOCUMENT_CANCELLEDSigning ended without a complete set of signatures.{ "documentId", "cancellationReason", "signerId", "cancelledAt" }
DOCUMENT_RESTOREDA 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).