Configure and verify webhooks
Saved webhook addresses are deprecated. Pass webhook_url directly in each POST /payment-links, POST /withdrawals, POST /conversions, or POST /fulfillments request. The request destination overrides the saved URL and receives signed events, retries, and redeliveries.
{
"display_name": "Order 1042",
"amount": "25.00",
"currency": "USD",
"project_id": "6d14a419-a00b-4fc0-9613-9c8959ed20c2",
"webhook_url": "https://merchant.example/webhooks/lirpay"
}During the transition, saved URLs remain a fallback only while NOTIFY_DEPRECATED_WH=true on the server. When the flag is removed, saved URL updates return 410 deprecated_webhook_removed, GET /webhook returns null, and requests without webhook_url receive no webhooks. Existing secrets and event history are retained.
If a webhook configuration exists for the key environment, keep using its signing secret. Otherwise, open merchant Settings, click Generate secret, then Copy secret, configure your receiver, and Save to activate the new value. Use POST /webhook/test with a JSON body containing url to test a request destination.
https://lirpay.org/api/v2/integration/webhookRead the deprecated saved webhook during the transition; returns null after compatibility ends.
https://lirpay.org/api/v2/integration/webhookDeprecated: create or update a saved URL during the transition. Returns HTTP 410 after compatibility ends.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
| url | URL | body | yes | HTTPS endpoint in live mode. Test mode also accepts HTTP. |
| event_types | string[] | body | yes | Non-empty list of supported events. |
| enabled | boolean | body | no | Delivery state. Defaults to true. |
Request
{
"url": "https://merchant.example/webhooks/lirpay",
"event_types": [
"payment.succeeded",
"balance.updated",
"withdrawal.completed"
],
"enabled": true
}The first PUT response includes a new secret. Store it because later GET responses expose only has_secret.
https://lirpay.org/api/v2/integration/webhookDisable webhook delivery for the current environment.
https://lirpay.org/api/v2/integration/webhook/testSend and record a signed test event.
https://lirpay.org/api/v2/integration/webhook/rotate-secretReplace the signing secret and return the new value once.
https://lirpay.org/api/v2/integration/webhook-eventsList event payloads and delivery state.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
| page | integer | query | no | Page number. Defaults to 1. |
| limit | integer | query | no | Items per page. Maximum 100. |
https://lirpay.org/api/v2/integration/webhook-events/{id}Read one payload and its delivery history.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
| id | uuid | path | yes | Resource identifier returned by a list or create operation. |
The delivery_history array includes attempt number, status, error, and timestamp.
https://lirpay.org/api/v2/integration/webhook-events/{id}/redeliverDeliver an existing event again.
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
| id | uuid | path | yes | Resource identifier returned by a list or create operation. |
| Idempotency-Key | string | header | yes | Unique key for this monetary operation. Maximum 255 characters. |
Allowlist source IPs
Production webhook deliveries come from payment-core egress. Allowlist 2.27.27.132 for both test and live events.
2.27.27.132— webhook source IP- Do not allowlist
2.27.27.134. That address is HTTPS ingress forlirpay.orgonly. - Deliveries currently use IPv4 only. Verify the HMAC signature even if you filter by IP.
Verify each signature
Compute a hexadecimal Hash-based Message Authentication Code using SHA-256 (HMAC-SHA256) over the untouched request body.
import { createHmac, timingSafeEqual } from "node:crypto";
const expected = createHmac("sha256", webhookSecret)
.update(rawBody)
.digest("hex");
const valid = timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(signature, "hex"),
);- Read the event identifier from
X-Lirpay-Event-Id - Read the environment from
X-Lirpay-Mode - Return a
2xxresponse after persisting the event - Deduplicate processing by event identifier
- Live deliveries are retried up to eight times. Test-mode events are never retried
Subscribe to supported events
payment.succeeded,payment.failed,payment.expired,payment.refund_required,payment.refunded,payment.chargebackbalance.updatedwithdrawal.processing,withdrawal.completed,withdrawal.failedconversion.completed