Configure endpoints, verify signatures, redeliver, and troubleshoot. Follow this sequence when events do not arrive.
Webhook Configuration and Troubleshooting
Configuration
Enter the endpoint URL under “Developer Center → Webhook” in the merchant portal. Configure sandbox and production separately— delivery is filtered by environment. A wrong environment results in no events, not someone else's events.
No Events? Check in This Order
1. Check Delivery Records First
GET /v1/webhooks/deliveries Returns the result of each delivery. Three cases:
| Record shows | Meaning | Action |
|---|---|---|
| No delivery record | This event was never sent to you | See step 2 below |
| Record exists, non-2xx | Sent, but your endpoint rejected it | Check your own logs |
Record exists, dead | Retries exhausted | Fix the issue, then redeliver |
2. No Delivery Record Means the Event Does Not Belong to You
The two most common causes:
- Event type not subscribed. We only send subscribed types.
- The business operation does not belong to your merchant. Cross-merchant events are not delivered; this is isolation, not failure.
3. Redeliver After Fixing the Issue
POST /v1/webhooks/deliveries/{id}/redeliver
Redelivery uses the original event body, with an unchanged z-event-id— your deduplication logic must therefore use z-event-id, or you may discard the redelivery yourself.
Retry Schedule
After delivery failure (non-2xx, timeout, or connection failure), backoff follows this schedule, in minutes:
1 ─► 5 ─► 30 ─► 120 ─► 360 ─► dead
5 waits + the 6th delivery; only failure of delivery 6 moves it to dead and triggers a merchant portal alert. Timeout is 10 seconds.
⚠ The final retry is about 8.6 hours later. A longer outage will move all affected events
to
dead; recovery then requiresredeliver, listing and resending them individually.Prefer returning 200 first and processing asynchronously, instead of continuously rejecting throughout an outage.
Any 2xx counts as success. We do not parse the response body, so its contents have no effect on us.
Request Headers
| Header | Content |
|---|---|
z-event-id | Unique event ID. Use this as your deduplication key |
z-event-type | Event type |
z-signature | t=<unix秒>,v1=<base64> |
Signature verification:
v1 == base64( HMAC-SHA256( webhook_secret, "<t>." + 原始请求体 ) )
⚠ Validate
twith a ±300-second tolerance, or an intercepted old request can be replayed indefinitely.
⚠ Compute HMAC over the original bytes, not a deserialized and reserialized body—
different key order or indentation changes the signature, one of the most common causes of 401.
What Your Endpoint Should Look Like
1. 立刻读出 z-event-id,查一次「处理过没有」
2. 处理过 → 直接回 200(别再处理一遍)
3. 没处理过 → 落库、回 200、异步去做后续
⚠ Do not perform slow work before returning 200. Our 10-second timeout triggers redelivery—
even if your system actually finished processing. The same operation may then be handled twice.
⚠ The event only says something changed; it is not a ledger fact. Query the corresponding
detail endpoint and merge forward by
status_version; event and polling response order is not guaranteed.
⚠ Return 401 on signature failure, not 200. A 200 tells us the event was received,
so it will not be sent again—even though you processed none of it.
Related Guides
- Webhook Overview—event body and signature algorithm
- Signature Debugger—compare signature strings character by character