Webhook payload

Verify and consume the signed delivery.

After the last signer, NoSign delivers the sealed PDF (base64) plus the ordered audit bundle to your callback_url. This page covers that final signing.completed delivery. For the lighter-weight lifecycle events (signer.signed, signing.declined, signing.expired) and zero-downtime secret rotation, see Webhooks — events & rotation.

Verifying the HMAC signature

NoSign signs the raw request body with HMAC-SHA256 and sends it in the X-NoSign-Signature header.

$expected = hash_hmac('sha256', $rawBody, $webhookSecret);
if (!hash_equals($expected, $request->header('X-NoSign-Signature'))) {
abort(401);
}

During a secret rotation window the X-NoSign-Signature header carries multiple digests (one per active secret); accept the delivery if any digest matches.

Return 2xx only after you have durably stored the sealed PDF — NoSign will not delete until you do. Delivery uses exponential-backoff retries with a dead-letter path.

Examples are illustrative; verify header and field names against your NoSign instance.

Payload structure

Field names below are illustrative. Verify against your NoSign instance’s API.

{
"signing_request_id": "sr_...",
"status": "completed",
"sealed_document": "<base64-encoded sealed PDF>",
"audit": [
{
"event": "request_created",
"actor": "api_key:named-key",
"timestamp": "2026-06-07T13:00:00Z",
"document_hash": "sha256:..."
},
{
"event": "signer_verified",
"actor": "signer:ada@example.com",
"timestamp": "2026-06-07T13:05:00Z"
},
{
"event": "signer_completed",
"actor": "signer:ada@example.com",
"timestamp": "2026-06-07T13:07:00Z",
"document_hash": "sha256:..."
},
{
"event": "document_sealed",
"timestamp": "2026-06-07T13:07:05Z",
"document_hash": "sha256:..."
}
]
}

Key properties

FieldDescription
signing_request_idID of the completed signing request
statuscompleted
sealed_documentBase64-encoded sealed PDF (PAdES-B-T)
auditOrdered array of audit events — every step of the ceremony

Audit event fields

Each audit event records:

Delivery guarantees

NoSign delivers the webhook with exponential-backoff retries. If all retries are exhausted, the delivery is moved to a dead-letter path and visible in the admin dashboard for manual retry.

NoSign does not delete the signing request until your platform returns 2xx. This is the hard gate. Return a non-2xx response or let the request time out, and NoSign will retry.