Webhooks and results
After sending a signing, use webhooks to bring its results back into your application. The same document-completion event covers uploaded PDFs and documents generated from contracts.
Register your listener before sending if you need to capture the entire workflow. Complete authentication first; the examples use KREBIT_API and ACCESS_TOKEN from that guide.
Register a listener
Create one registration for each event you want to receive. The target must be an HTTPS URL:
curl --fail-with-body --silent --show-error --request POST \
"${KREBIT_API}/webhooks" \
--header "Authorization: Bearer ${ACCESS_TOKEN}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"event":"signing.document.completed","target":"https://yourapp.example.com/webhooks/krebit"}'
Store the returned registration ID and secret securely. You need the secret to verify deliveries. See Create a webhook for the full response.
Event catalog
Every delivery has an id, an event name, and an event-specific data object.
| Event | Payload | Use it to |
|---|---|---|
signing.sent | data.signing | Record that the signing was sent. |
signing.document.completed | data.document | Retrieve the signed document and any contract values. |
signing.cancelled | data.signing and data.cancel_message | Record a cancellation. |
A document-completion event applies to one document. Fetch the signing to check is_completed if your application needs to know whether the entire signing is complete.
Verify signatures
Read X-Signature and verify it against the raw request body, before parsing or processing the event. X-Client-Id identifies the OAuth client associated with the registration.
For a Node.js backend:
import crypto from 'node:crypto';
function verifySignature(rawBody: Buffer, signature: string | undefined, secret: string): boolean {
if (!signature || !/^[a-f0-9]{64}$/i.test(signature)) {
return false;
}
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
const received = Buffer.from(signature, 'hex');
return crypto.timingSafeEqual(expected, received);
}
Use the secret for the matching registration. Missing or malformed signatures should be rejected. Your HTTP framework must preserve the raw body; reserializing parsed JSON can change the bytes and invalidate the signature.
Retrieve the result
After verifying a signing.document.completed event:
- Read
data.document.signing_idanddata.document.id. - Download
GET /api/1.0/signings/{signing_id}/documents/{id}/download-signed. - If
data.document.contract_idis notnull, fetch the contract as described below. - Save your processing result using the event
idto avoid processing a retry twice.
Use your API bearer token for these retrieval requests. The webhook secret is only for signature verification.
Retrieve fields from a signed contract
This excerpt shows the IDs in a completion event for a document generated from a contract:
{
"id": "4be08bac-7e3c-4615-a018-cd47c3d403ad",
"event": "signing.document.completed",
"data": {
"document": {
"id": "9dc693de-2b1b-4adb-9d56-95830c831d56",
"signing_id": "0b63a3fa-2962-4aa5-b7cf-e4bc3e91c119",
"contract_id": "24f8bb3d-e625-4e9c-8ce0-2a38ea2b2344"
}
}
}
Fetch GET /api/1.0/signings/{signing_id}/contracts/{contract_id}. Its fields array contains the final values, including those entered by recipients. If contract_id is null, skip that lookup.
See Create a contract from a template for a cURL example and the completion event reference for the full payload.
Reliability and troubleshooting
- Verify the event, durably record or enqueue it, then return
200promptly. Perform downloads and other work asynchronously. - Deliveries can be retried. Make processing idempotent using the event
id, and do not assume events arrive in order. - If signature verification fails, check the registration secret, signature header, and raw body handling.
- If deliveries stop, check the registration, target URL, and your server's responses. Use the API to reconcile signing and document status after an outage.
- Keep secrets, document contents, and contract field values out of routine logs.
Next step
Test the full path with a recipient address you control: send, sign, receive the event, and confirm the resulting PDF and values in your application. Use API conventions for error and retry handling.