Setting up an endpoint
Add a webhook endpoint in the dashboard, pick the events you care about, and store the signing secret on your server.
A webhook endpoint is a URL on your server that XPay POSTs JSON events to whenever something interesting happens: a Checkout Session completes, a Refund lands, a Customer is created. You add it once in the dashboard, pick the events you want, and copy the signing secret onto your server so you can verify every payload before acting on it.
Webhook endpoints are managed only in the dashboard, not over the API. The same is true for the signing secret. Do everything below from app.xpay.app.
Open the Webhooks page
In the dashboard, open the Developers page and click the Webhooks tab. The list shows every endpoint configured for the current mode.
Test mode and live mode keep separate endpoint lists. Use the Test / Live switch at the bottom of the sidebar to flip between them. An endpoint created in test mode does not exist in live mode, and vice versa.
Create an endpoint
Click Add endpoint
Top-right of the Webhooks tab. If the list is empty, the same action is on the empty state as Create webhook endpoint.
A side panel opens with two required fields: the URL and the events.
Enter the endpoint URL
Type a fully qualified URL into Endpoint URL. The form validates the shape, not reachability. The URL must be one your server actually serves.
A few rules:
- Include the protocol (
https://...). The form rejects values that don't parse as URLs. - Use HTTPS in production. Plain HTTP is accepted by the form, but a reachable HTTPS URL with a valid certificate is what you want once you ship.
http://localhost:...is fine in test mode while you build (see Local development for tunnels). - One endpoint per URL. If you need to fan out to two systems, create two endpoints with different URLs, or have one handler forward.
Pick events to listen to
Below the URL field is Select events to listen to. The picker is split into two sections:
- A Recommended section at the top, surfacing the high-signal events most integrations subscribe to first (Checkout Session completion, refund lifecycle, customer lifecycle).
- An Advanced collapsible below it that holds the rest, grouped by resource.
Click any group to expand it and tick individual events. Each group has an in-group Select all checkbox if you want every event in that group at once. The same resource can appear in both sections when its events span both buckets — Checkout Sessions, for example, shows checkout.session.completed under Recommended and the rest of its lifecycle under Advanced.
You must pick at least one. A common starting set:
checkout.session.completedfor the lifecycle of the session you created.refund.createdandrefund.failedto track reversals.customer.created,customer.updated,customer.deletedto keep your customer table in sync.
Add charge.succeeded / charge.failed (under Advanced → Charges) if your data model needs to react at the charge level. Subscribe only to the events your handler actually reads — every subscription costs a delivery, a retry budget, and a signature verification on your server.
For the full list, see Event reference.
Click Add endpoint to save
XPay creates the endpoint and immediately surfaces a Webhook signing secret dialog with a whsec_* value.
Copy it now. The dashboard will not show it again. If you lose it, your only path is to delete the endpoint and create a new one.
Store it on the server that runs your handler, typically as an environment variable like XPAY_WEBHOOK_SECRET loaded once at boot. Click Done to close the dialog and return to the list.
The signing secret
Every endpoint has its own whsec_* secret. XPay signs every event delivered to that endpoint with HMAC-SHA256 using this secret, and your handler uses the same secret to confirm that an incoming event really came from XPay.
Three rules:
- Never put the secret in client code. It belongs on the server. A leaked secret lets anyone forge events into your handler.
- Keep test and live secrets separate. Each endpoint has its own. Don't reuse one environment variable for both.
- Treat the secret as opaque. It's a random string with a
whsec_prefix. Don't parse it, don't truncate it.
If you suspect a secret leaked, delete the endpoint and recreate it. The dashboard does not surface a rotate-secret action today.
Test mode and live mode endpoints
Test and live are isolated environments with their own data and their own webhook endpoints. The mode switch decides which list the dashboard shows; the API key prefix (sk_test_* vs sk_live_*) decides which list events fire against.
You'll typically want at least two endpoints:
- A test endpoint pointing at a tunnel into your dev box, or at a staging server.
- A live endpoint pointing at the URL your production server actually serves.
Each gets its own signing secret. Build and verify against the test endpoint first, then add the live endpoint right before you flip your account into live mode.
Manage your endpoints
The actions menu on each row (the ⋮ button at the right) has three options.
| Action | What it does |
|---|---|
| Edit webhook | Change the URL, change the subscribed events, or both. The signing secret stays the same, so your verification code keeps working. |
| Disable webhook / Enable webhook | Stop or resume deliveries without losing the configuration. Useful while debugging a handler. |
| Delete webhook | Permanently removes the endpoint. The signing secret becomes invalid. Pending deliveries to that endpoint stop. |
Disabled endpoints stay in the list with a Disabled badge. They receive no events and run no retries while disabled. Re-enabling resumes new deliveries; events that fired during the disabled window are not back-filled.
Where to next
Verifying signatures
Confirm every event came from XPay before you trust it. HMAC-SHA256 with replay protection, in Node and Python.
Replaying and retries
The retry schedule when your handler returns non-2xx, and how to manually replay an event from the dashboard.
Local development
Tunnel webhook deliveries to your laptop while you build the handler.
Event reference
Every event you can subscribe to, when it fires, and the object it carries.
Object model
What each event's data.object contains, and which IDs to keep on your order record.
Test mode and test cards
Run real test payments through your endpoint before going live.
Elements
Build your own checkout UI. Your form collects customer details, our PaymentElement handles cards and local methods, your code calls confirm(). Maximum control.
Verifying signatures
Confirm every webhook is really from XPay before you trust it. HMAC-SHA256 over the raw body, with a 5-minute replay window.