ZyloPaydocs

Webhooks

Receive signed events at your own URL when payments, refunds and terminals change.

ZyloPay sends an HTTP POST to your endpoint each time something happens in your account: a payment settles, a refund completes, a terminal is added. Webhooks are how your systems learn about payments that nobody asked about, such as a sale started by a cashier on the terminal.

The request

POST /zylopay/webhooks HTTP/1.1
Host: example.com
Content-Type: application/json; charset=utf-8
User-Agent: ZyloPay-Webhooks/1.0 (+https://docs.zylopay.com/webhooks)
ZyloPay-Signature: t=1790604160,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
ZyloPay-Event-Id: evt_7Hq2Zp9LwK4mXr8Vb3Ns1Td5
ZyloPay-Event-Type: payment.succeeded
ZyloPay-Delivery-Id: wdl_8Tq3Zm1Xk6Pv9Rw2Lb4Ns7Hd
ZyloPay-Delivery-Attempt: 1

{"id":"evt_7Hq2Zp9LwK4mXr8Vb3Ns1Td5","object":"event","type":"payment.succeeded","api_version":"2026-09-28","livemode":false,"created":"2026-09-28T14:02:40.000Z","data":{"object":{"id":"pay_1042","object":"payment","…":"…"}}}

The body is exactly the event object, the same as GET /v1/events/{id}. data.object is the object as it was when the event happened. The event types page lists every type and its payload.

Set up an endpoint

Build the handler. It must:

  1. read the raw request body, before any JSON parsing;
  2. verify the signature and reject anything that fails;
  3. record the event ID and ignore IDs it has already processed;
  4. answer 2xx within 10 seconds, then do slow work asynchronously.

Register the URL, in the dashboard (Developers → Webhooks → Add endpoint) or with the API:

const endpoint = await zp.webhookEndpoints.create({
  url: 'https://example.com/zylopay/webhooks',
  enabled_events: ['payment.succeeded', 'payment_intent.*', 'refund.*'],
  description: 'Order service',
});

The response contains the signing secret, whsec_…, once. Store it in your secrets manager.

Send a test event and check that your handler answers 2xx. See Testing webhooks.

Endpoint rules

  • One mode. An endpoint belongs to the mode of the key or dashboard view that created it. It receives only that mode's events. Create one endpoint per mode.
  • URL. Live endpoints must use https. Test endpoints may use http. Ports 80, 443 and 1024-65535 only. No user name or password in the URL, no fragment.
  • Public addresses only. ZyloPay refuses URLs that resolve to private, loopback, link-local or reserved addresses (localhost, 10.0.0.0/8, 192.168.0.0/16, 169.254.169.254, *.internal…), when you create the endpoint and again at every delivery. Use a tunnel to receive events on a development machine.
  • No redirects. A 3xx answer counts as a failure.
  • Up to 16 endpoints per mode.
  • Subscriptions. enabled_events takes exact types, families such as refund.*, or * for all. Subscribe only to what you handle.

Security

  • Always verify the signature. Anyone can send a POST to your URL.
  • The signature covers a timestamp, which stops old deliveries being replayed. See replay protection.
  • Do not trust data.object for high-value decisions without the signature check. If in doubt, re-read the object from the API.

Next

On this page