Webhooks are a way for Lopay to notify partners when a significant event has taken place.Available events#
The table below contains the events that it is possible to subscribe to. If you would like any new events added, please get in touch with your use case and we will usually be able to add support for the new event.Event | Description |
---|
authorization.granted | Authorization granted for merchant access. Partner can now access merchant through the partner API. |
authorization.revoked | Authorization revoked for merchant access. Partner will no longer have access to merchant. |
merchant.capabilities.updated | Merchant capabilities updated. |
merchant.payout.created | A payout to the merchant's default bank account has been initiated. |
merchant.payout.paid | Payout has landed in merchant's default bank account. |
merchant.payout.failed | Payout has failed. |
merchant.payout.cancelled | Payout has been cancelled. |
payment.success | Payment was successful. |
payment.failed | Payment has failed. |
paymentLink.created | Payment link created. |
paymentLink.updated | Payment link updated. |
paymentLink.revoked | Payment link has been revoked. |
Event data structure#
All events share the following basic structure:{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "payment.success",
"data": {}
}
Example webhook events#
Below are example webhook payloads for all available events.authorization.granted#
{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "authorization.granted",
"data": {
"merchantId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
}
}
authorization.revoked#
{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "authorization.revoked",
"data": {
"merchantId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
}
}
merchant.capabilities.updated#
{
"id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
"object": "event",
"createdAt": "2024-09-11T00:03:04.000Z",
"type": "merchant.capabilities.updated",
"data": {
"merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420"
"capabilities": {
"paymentLinksEnabled": true,
"foreignCardsEnabled": false
}
}
}
merchant.payout.created#
{
"id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
"object": "event",
"createdAt": "2024-09-11T00:03:04.000Z",
"type": "merchant.payout.created",
"data": {
"merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
"payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
"payments": [
{
"id": "30c1cae6-c192-471f-a632-526115ceb5ad",
"paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
}
]
}
}
merchant.payout.paid#
{
"id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
"object": "event",
"createdAt": "2024-09-11T00:03:04.000Z",
"type": "merchant.payout.paid",
"data": {
"merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
"payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
"payments": [
{
"id": "30c1cae6-c192-471f-a632-526115ceb5ad",
"paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
}
]
}
}
merchant.payout.failed#
{
"id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
"object": "event",
"createdAt": "2024-09-11T00:03:04.000Z",
"type": "merchant.payout.failed",
"data": {
"merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
"payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
"payments": [
{
"id": "30c1cae6-c192-471f-a632-526115ceb5ad",
"paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
}
]
}
}
merchant.payout.cancelled#
{
"id": "cf974cce-71ee-4243-8261-6ea4093cb7ee",
"object": "event",
"createdAt": "2024-09-11T00:03:04.000Z",
"type": "merchant.payout.cancelled",
"data": {
"merchantId": "f73e2e62-eea4-45f9-b2b6-25a9ccaff420",
"payoutId": "a14117e3-862c-4425-b0a6-e2754d9b2eaf",
"payments": [
{
"id": "30c1cae6-c192-471f-a632-526115ceb5ad",
"paymentLinkId": "71854521-8edc-4546-89e3-2163869d3571"
}
]
}
}
payment.success#
{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "payment.success",
"data": {
"paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
"paymentId": "9b8e457c-f679-4d2f-9551-ee8aaf7760f7"
}
}
payment.failed#
{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "payment.failed",
"data": {
"paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
}
}
paymentLink.created#
{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "paymentLink.created",
"data": {
"paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
}
}
paymentLink.updated#
{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "paymentLink.updated",
"data": {
"paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
}
}
paymentLink.revoked#
{
"id": "cbb90acf-a45d-4b2a-84dd-b6962921d6aa",
"object": "event",
"createdAt": "2024-06-12T19:03:04.456Z",
"type": "paymentLink.revoked",
"data": {
"paymentLinkId": "2a4ceed-0d10-4fc4-b9b2-f5b4b459dc5c"
}
}
Configuring webhooks#
You can configure webhook subscriptions in multiple ways:2.
Lopay Partner Webhook Portal
You can use the POST /api/1/partner/webhooks
to create a webhook subscription and PUT /api/1/partner/webhooks/{id}
endpoint to update an existing webhooks subscription.Alternatively, you can configure your webhook subscriptions using the webhook portal. In order to do this, you will need to create a login link using GET /api/1/partner/webhooks/portal-link
. Please see the Webhook subscriptions
section for more details.Verifying webhook requests#
Each webhook call includes three headers with additional information that are used for verification:svix-id
: the unique message identifier for the webhook message. This identifier is unique across all messages, but will be the same when the same webhook is being resent (e.g. due to a previous failure).
svix-timestamp
: timestamp in seconds since epoch.
svix-signature
: the Base64 encoded list of signatures (space delimited).
Constructing the signed content#
The content to sign is composed by concatenating the id, timestamp and payload, separated by the full-stop character (.). In code, it will look something like:Where body is the raw body of the request. The signature is sensitive to any changes, so even a small change in the body will cause the signature to be completely different. This means that you should not change the body in any way before verifying.Determining the expected signature#
So to calculate the expected signature, you should HMAC the signed_content from above using the base64 portion of your signing secret (this is the part after the whsec_
prefix) as the key. For example, given the secret whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw
you will want to use MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw
.For example, this is how you can calculate the signature in Node.js (JavaScript):This generated signature should match one of the ones sent in the svix-signature
header.The svix-signature
header is composed of a list of space delimited signatures and their corresponding version identifiers. The signature list is most commonly of length one. Though there could be any number of signatures. For example:v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE= v1,bm9ldHUjKzFob2VudXRob2VodWUzMjRvdWVvdW9ldQo= v2,MzJsNDk4MzI0K2VvdSMjMTEjQEBAQDEyMzMzMzEyMwo=
Make sure to remove the version prefix and delimiter (e.g. v1,) before verifying the signature.Please note that to compare the signatures it's recommended to use a constant-time string comparison method in order to prevent timing attacks.Webhook retries#
Each message is attempted based on the following schedule, where each period is started following the failure of the preceding attempt:10 hours (in addition to the previous)
If an endpoint is removed or disabled delivery attempts to the endpoint will be disabled as well.For example, an attempt that fails three times before eventually succeeding will be delivered roughly 35 minutes and 5 seconds following the first attempt.Indicating successful delivery#
The way to indicate that a webhook has been processed is by returning a 2xx
(status code 200-299) response to the webhook message within a reasonable time-frame (15s with Lopay). Any other status code, including 3xx
redirects are treated as failures. Modified at 2025-07-22 09:23:18