Use webhooks to receive terminal verification outcomes without polling.
Current terminal events
The current terminal events are:
verification.completedverification.review_requiredverification.failed
Webhook configuration is stored per client app. Each app owns its own endpoint and signing secret.
Required headers
Every outbound request includes:
Content-Type: application/jsonUser-Agent: docufykit-webhooks/1.0X-Webhook-EventX-Webhook-IdX-Webhook-TimestampX-Webhook-Signature
Signature format
The signature format is:
sha256=HMAC_SHA256(secret, timestamp + "." + delivery_id + "." + raw_body)
Verify the signature against the raw request body bytes, not reserialized JSON.
import crypto from "node:crypto";
function verifyDocufykitWebhook({
secret,
timestamp,
deliveryId,
rawBody,
signature,
}: {
secret: string;
timestamp: string;
deliveryId: string;
rawBody: Buffer;
signature: string;
}) {
const payload = Buffer.concat([
Buffer.from(timestamp, "utf8"),
Buffer.from(".", "utf8"),
Buffer.from(deliveryId, "utf8"),
Buffer.from(".", "utf8"),
rawBody,
]);
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(payload).digest("hex");
const actual = Buffer.from(signature, "utf8");
const wanted = Buffer.from(expected, "utf8");
return (
actual.length === wanted.length &&
crypto.timingSafeEqual(actual, wanted)
);
}
Retry behavior by environment
Sandbox
- one delivery attempt only
- no automatic retry schedule
- no
dead_letterstate - failed deliveries stay in
faileduntil manual replay
Production
If your endpoint does not return 2xx, the platform retries automatically on this schedule:
- 30 seconds
- 2 minutes
- 10 minutes
- 1 hour
- 6 hours
- 24 hours
After the final retry, the delivery moves to dead_letter.
Replay workflow
Customers can:
- inspect the latest webhook request and response in the portal
- see failed and dead-letter deliveries
- replay a delivery manually from the deliveries page
Integration guidance
- Use a separate webhook URL per environment.
- Use separate apps and environment-prefixed API keys for sandbox and production.
- Treat signed webhook delivery as the primary async result path.
- Use REST lookups as a secondary inspection path, not a replacement for signature verification.