API docs
Events
Webhooks
Onboardly sends events to your configured URL whenever the state of an onboarding or KYC verification changes. Every payload is signed with HMAC-SHA256, so you can verify its authenticity.
Event types
onboarding.created | a new onboarding process was created. |
onboarding.completed | the employee finished onboarding. |
onboarding.signed | a document was signed. |
onboarding.fully_signed | all parties signed the documents. |
kyc.passed | identity verification succeeded. |
kyc.failed | identity verification failed. |
Payload format
The payload is sent via POST as JSON:
{
"event": "onboarding.completed",
"tenantId": "uuid",
"companyId": "uuid",
"onboardingId": "uuid",
"timestamp": "2026-07-14T12:00:00.000Z",
"data": { /* depends on the event type */ }
}Headers
X-Onboardly-Signature | HMAC-SHA256 signature of the request body, keyed with the tenant's webhookSecret. |
X-Onboardly-Event | the event type (e.g. onboarding.completed). |
Signature verification
Compute HMAC-SHA256 over the raw request body using your webhook secret (available in the tenant settings) and compare the result with the X-Onboardly-Signature header in a timing-safe way. Reject the request if the signatures do not match.
import crypto from "node:crypto";
function verifyOnboardlyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody, "utf8")
.digest("hex");
// constant-time comparison
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}Verify against the raw body
Compute the HMAC before the body is parsed into an object — re-serializing the JSON can change the bytes and invalidate the signature.Retries and ordering
Delivery runs from a durable queue with retries on a 1 min → 5 min → 30 min → 2 h → 12 h schedule (6 attempts; once exhausted, the event moves to the dead state). Respond with a 2xx code as quickly as possible and do heavier work asynchronously. Design your receiver to be idempotent — the same event may arrive more than once.