Webhooks
Webhook Use Case
Use our webhooks to be notified about finished syncs. This allows you to fetch any changes that occurred during a sync and to keep your database up to date without scheduling/polling. Easily test webhooks with Webhook.site.
Enable Webhooks
You can configure your Kombo webhooks in the dashboard directly in the webhooks tab. After creating the first webhook, a random webhook secret will be generated and shown. You can learn how to use it in Validate the data.
Data Schema
Our webhooks follow this schema:
{
"id": "5gjAtURLPbnTiwgkaBfiA3WJ",
"type": "sync-finished",
"data": {
"sync_id": "B89SCXXho7Yw8PGo8AKJxLn4",
"sync_state": "SUCCEEDED",
"sync_started_at": "2021-09-01T12:00:00.000Z",
"sync_ended_at": "2021-09-01T12:30:00.000Z",
"sync_duration_seconds": 1800,
"integration_id": "personio:CBNMt7dSNCzBdnRTx87dev4E",
"integration_tool": "personio",
"integration_category": "HRIS",
"end_user": {
"origin_id": "36123",
"creator_email": "user@example.com",
"organization_name": "Acme, Inc."
},
"log_url": "https://app.kombo.dev/env/production/logs/C3xUo6XAsB2sbKC7M1gyXaRX"
}
}
Possible values for the sync_state
on the sync-finished
webhook:
enum SyncState = {
"SUCCEEDED", // Sync completed successfully
"CANCELLED", // Sync was cancelled
"FAILED", // Failed with unrecoverable errors
"PARTIALLY_FAILED", // Failed with partial errors
"AUTHENTICATION_FAILED", // Authentication failed
"TIMED_OUT", // Timed out before completion
}
Validate the data
Anyone could post data to your webhook URL. That’s why we’re signing each
request with a secret specific to your Kombo account. The secret is called
Kombo Webhook Secret
and will be sent to you when we activate Webhooks for
you.
Each valid webhook POST from us will include the X-Kombo-Signature
header.
Validate it by:
- Using HMAC-SHA256 to sign the request body with your
Kombo Webhook Secret
- Digest with base64url encoding.
Our ‘base64url’ encoding does not include the optional trailing ’=’ padding characters.
Here are some examples of how you could achieve this in a few different languages:
import { createHmac } from 'node:crypto'
const signatureHeader = req.headers['x-kombo-signature']
// Get the raw UTF-8-encoded string body because this was used for signing
const body = request.body
// Or if you use a framework that parses the body for you, you can use this.
// Note: This is not the same as JSON.stringify(request.body)
const body = JSON.stringify(request.body, null, 2)
const signature = createHmac('sha256', KOMBO_WEBHOOK_SECRET)
.update(body, 'utf8')
.digest('base64url')
const isValidRequest = signature === signatureHeader
You have to use exactly the same string we use for signing. This means that
you should optimally use the raw body. Alternatively, you can manually turn
the parsed body into a string again. In that case, make sure to use the exact
same encoding and indentation (e.g., JSON.stringify(body, null, 2)
in
JavaScript).
Testing webhooks
The list of all created webhook has two buttons on the right. One is for deleting the webhook, the other is for sending a test request. This test request will contain dummy data, but will use the correct data schema.
Be careful when using this feature in production! It will send invalid data to your webhook.
Testing locally
For local development you can use a service like localtunnel or ngrok. These tools allow you to expose a local port through a public URL provided by them. The setup is very straightforward: Once you’ve started a tunnel, simply add the provided URL as a webhook in the Kombo dashboard. You can then send test requests to validate that your endpoint is working properly.