Skip to main content

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.

EventPayloadUse it to
signing.sentdata.signingRecord that the signing was sent.
signing.document.completeddata.documentRetrieve the signed document and any contract values.
signing.cancelleddata.signing and data.cancel_messageRecord 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:

  1. Read data.document.signing_id and data.document.id.
  2. Download GET /api/1.0/signings/{signing_id}/documents/{id}/download-signed.
  3. If data.document.contract_id is not null, fetch the contract as described below.
  4. Save your processing result using the event id to 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 200 promptly. 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.