Webhooks
Use webhooks to get notifications sent to your backend servers every time an Event is created, in real time.
A Webhook object consists of a destination URL and a set of events types to receive. If an event matches multiple webhooks, it will be sent to all of them.
When an event happens, the URL is sent an HTTP POST request, with the event JSON as request body.
Registering webhooks
To register a new webhook, you need to have a URL in your app that Kernel can call. You can configure a new webhook from the Kernel dashboard under Webhooks. Give your webhook a name, pick the events you want to listen for, and add your URL.
Consuming webhooks
When your app receives a webhook request from Kenel, check the type
attribute to see what event caused it. The first part of the event type will tell you the payload type, e.g., a transfer
, a card_payin
, etc. In the payload
, you will find the actual data for the event.
Example webhook payload
{
"id": "ev_3y7cfc9mxnjjy7r7e4q1",
"project_id": "prj_3y7c8zrgxnrvln3x8avh",
"type": "transfer_created",
"correlation_id": "trf_3y7cfc9jv6nubasjbtk1",
"payload": {
"transfer": {
"id": "trf_3y7cfc9jv6nubasjbtk1"
// ...
}
},
"created_at": "2023-10-10T10:09:23.864322048Z"
}
In the example above, a transfer was created
, and the payload type is a transfer
.
Event types
- Name
card_payin_dispute_created
- Description
- A dispute has been created for a card payin.
- Name
card_payin_settled
- Description
- A card payin has been settled.
- Name
bank_payin_created
- Description
- A bank payin has been created.
- Name
bank_payout_completed
- Description
- A bank payout has been completed.
- Name
bank_payout_failed
- Description
- A bank payout has failed.
- Name
bank_payout_refunded
- Description
- A bank payout has been refunded.
- Name
card_payin_dispute_won
- Description
- A dispute for a card payin has been won.
- Name
card_payin_dispute_lost
- Description
- A dispute for a card payin has been lost.
- Name
card_payin_authorized
- Description
- A card payin has been authorized.
- Name
card_payin_declined
- Description
- A card payin has been declined.
- Name
transfer_created
- Description
- A transfer has been created.
Example payload
{
"id": "ev_3y7cfc9mxnjjy7r7e4q1",
"project_id": "prj_3y7c8zrgxnrvln3x8avh",
"type": "transfer_created",
"correlation_id": "trf_3y7cfc9jv6nubasjbtk1",
"payload": {
"transfer": {
"id": "trf_3y7cfc9jv6nubasjbtk1",
"meta": {},
"value": {
"amount": 100000,
"currency": "EUR"
},
"created_at": "2023-10-10T10:09:23.813203968Z",
"project_id": "prj_3y7c8zrgxnrvln3x8avh",
"updated_at": "2023-10-10T10:09:23.835560371Z",
"split_source": null,
"source_account_id": "acc_3y7cfahqtgplzfv5bkl1",
"split_destination": null,
"source_transaction_id": "tx_3y7cfc9jzct9afm4rc8h",
"destination_account_id": "acc_3y7cf5sclx1ze5fe2gv1",
"destination_transaction_id": "tx_3y7cfc9jzct9afm4rc91"
}
},
"created_at": "2023-10-10T10:09:23.864322048Z"
}
Security
Webhook delivery contents are cryptographically signed. This allows you to verify the webhook request comes indeed from Kernel Payments.
Verifying the signature and discarding incorrectly signed requests is strongly recommended. Not doing so allows any attacker on the internet to send fake events to your server. This can cause your server to think a payment has been received that in reality hasn't, for example.
The signature is included in the X-Kernel-Sig-SHA256
header, and contains the HMAC-SHA256
hash of the request body, using the webhook's secret
as a key.
You can find working code snippets to validate signatures in this GitHub repo
Verifying a webhook request
const signature = Buffer.from(req.headers["x-kernel-sig-sha256"], "hex");
const expectedSignature = crypto.createHmac("sha256", secret).update(body).digest();
const ok = crypto.timingSafeEqual(signature, expectedSignature);
if (!ok) {
return res.status(400).send("Invalid signature");
}
// Continue processing the request
return res.status(200).send("OK");
Delivery
Webhook delivery is 'At Least Once'.
Kernel Payments expects a HTTP 200 OK
response from your application. Any other HTTP status code, as well as inability to receive a response (due to network failures, TLS certificate errors, timeouts...) are treated as failures.
In case of failures, the delivery is retried with an exponential backoff, for up to 5 days after the event occurred.
Webhooks can be delivered out-of-order, especially in the case of delivery failures.
You can view the delivery logs in the dashboard, by clicking on a webhook. The logs include the request and your server's response, which can be useful in diagnosing delivery problems.