Webhooks
This guide explains how to implement webhook handling for payment status notifications in your application. Webhooks provide real-time updates about payment statuses directly to your backend system.
Implementation Requirements
When creating a payment, you can provide a webhookUrl endpoint where we will send payment status notifications. If provided, your system must:
- Respond to webhook requests within 10 seconds
- Return a 2xx HTTP status code to acknowledge successful receipt
- Handle webhook payload validation
If your system fails to acknowledge a webhook, we will:
- Retry the webhook delivery up to 5 times
- Spread retries across a 72-hour period
- Send an email notification after the final unsuccessful attempt
Webhook Payload
Each webhook request contains a JWT token in the request body:
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXltZW50T3JkZXJJZCI6IjAxOTc1ODZjLWUzZjItNzNkNS04ZTI4LWMzMGM4YjY4YjQ3OSIsIm9yZGVyUmVmZXJlbmNlIjoiVEVTVC1kZjdhMzFmYy03MmQ0LTRmMmItYmJlZC1hNzlkZThkYTJkYjMiLCJwYXltZW50UHVycG9zZSI6IlRlc3Qgb3JkZXIgIzEyMzQiLCJwYXltZW50U3RhdHVzIjoiY29tcGxldGVkIiwicGF5bWVudERldGFpbHMiOnsiYW1vdW50IjoxMi4zNCwiY3VycmVuY3kiOiJFVVIiLCJkZWJ0b3JJYmFuIjoiTFQzNzczMDAwMTAwMTAyNjkzNjIifSwiZXZlbnQiOiJwYXltZW50LmNvbXBsZXRlZCJ9.Pbi6JJVqtY-J3jlcdAyd8DMkLQEjTRvdDSb85exjeeY"
}
The JWT token must be validated using your secret key to ensure the webhook's authenticity.
JWT Token Validation
import jwt from 'jsonwebtoken';
const token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXltZW50T3JkZXJJZCI6IjAxOTc1ODZjLWUzZjItNzNkNS04ZTI4LWMzMGM4YjY4YjQ3OSIsIm9yZGVyUmVmZXJlbmNlIjoiVEVTVC1kZjdhMzFmYy03MmQ0LTRmMmItYmJlZC1hNzlkZThkYTJkYjMiLCJwYXltZW50UHVycG9zZSI6IlRlc3Qgb3JkZXIgIzEyMzQiLCJwYXltZW50U3RhdHVzIjoiY29tcGxldGVkIiwicGF5bWVudERldGFpbHMiOnsiYW1vdW50IjoxMi4zNCwiY3VycmVuY3kiOiJFVVIiLCJkZWJ0b3JJYmFuIjoiTFQzNzczMDAwMTAwMTAyNjkzNjIifSwiZXZlbnQiOiJwYXltZW50LmNvbXBsZXRlZCJ9.Pbi6JJVqtY-J3jlcdAyd8DMkLQEjTRvdDSb85exjeeY';
const decoded = jwt.verify(token, 'your-secret-key');
Statuses
Webhooks will announce these status changes:
- Name
processing- Description
Payment order is being processing - we are waiting for banks confirmation. Eventualy it will become
completedorcanceled. In rare cases this can take up to two days.
- Name
completed- Description
Payment order has been successfully paid.
- Name
canceled- Description
Payment order was canceled by the client or the bank.
- Name
expired- Description
Payment session has expired without completion - user abandoned the payment.
- Name
failed- Description
Payment process failed due to technical issues on our end or with the banking system.
Decoded Webhook Payload Example
{
"paymentOrderId": "0197586c-e3f2-73d5-8e28-c30c8b68b479",
"orderReference": "TEST-df7a31fc-72d4-4f2b-bbed-a79de8da2db3",
"paymentStatus": "completed",
"paymentDetails": {
"amount": 12.34,
"currency": "EUR",
"debtorIban": "LT377300010010269362"
},
"event": "payment.completed"
}
Payment lifecycle
Normally there should be only one Payment order status change - from pending to the one of listed above. But there are some edge cases where it may change between the ones listed above.
You should know that:
- A payment order may transition from any other status (including
canceledandfailed) tocompleted. - Payment order will not transition from
completedto other statuses.