Skip to main content
Instead of polling List escrow transactions, let Payluk push escrow updates to you. Whenever an escrow you manage is created or changes status, Payluk sends a signed POST request to your registered callback URL.

Prerequisites

A webhook is sent only when all of these hold:
You’ve set a callback URL for the environment (test or live) in your dashboard business settings.
The escrow carries your merchantId: i.e. it was created through the API under your merchant account.
The escrow’s seller is one of your merchant customers (merchant_user).
If any is missing, no webhook fires and the underlying escrow operation still succeeds as normal.
Payluk picks the callback URL and signing key by the escrow’s environment: escrows created with a sk_live_ key post to your live callback URL and are signed with your live secret; sk_test_ escrows post to your test callback URL signed with your test secret.

Events

The event field is escrow.<status> (lower-cased), plus escrow.created when a new escrow is generated. Every status transition emits one event: See Escrow lifecycle for how these map to state and status.
Multi-quantity links emit events for each escrow independently; the original link and every cloned escrow. Match on data.id, not the paymentToken. See Multi-quantity escrows.

The payload

Every webhook body has the same envelope:
The data object mirrors the escrow you get from the API, including status, state, settlementType, milestones, totalQuantity, environment and merchantId.

Verify the signature

Each request carries an x-payluk-signature header: an HMAC-SHA512 of the raw JSON body, keyed with your environment’s secret key. Always verify it before trusting a payload.
Headers
Sign against the exact raw bytes of the request body. If you re-serialize the parsed JSON, key ordering or spacing may differ and the signature won’t match.

Delivery & retries

Acknowledge fast with a 2xx, then do heavy work asynchronously. If you need state that may have arrived out of order, re-fetch the escrow with Verify payment token using the paymentToken in the payload.

Best practices

Treat any request with a missing or mismatched x-payluk-signature as untrusted and reject it with 401. Use a constant-time comparison.
The same event may be delivered more than once (a retry after a slow 2xx). De-duplicate on data.id + event (or data.status) so reprocessing is a no-op.
Events are sent as state changes happen and may arrive out of order under retries. Trust data.status / data.state as the source of truth rather than the sequence of events.
Configure distinct callback URLs and verify each with its matching secret (sk_test_ vs sk_live_). The data.environment field tells you which one a payload belongs to.