The contract
Acknowledge fast
Ten seconds is the whole budget. Do the minimum synchronously and queue the rest.Idempotency
Every real event delivery carries a stableX-Webhook-Id, which also appears as id in the body. Retries of the same event reuse it.
When your endpoint is down
A failed delivery is retried on a fixed schedule — after 1 minute, 5 minutes, 30 minutes, 2 hours, then 12 hours — for a maximum of 6 attempts, about 14.5 hours from the first try. If you’re down for a deploy, deliveries resume once you’re back. After the sixth failed attempt the delivery is dead-lettered: it is never retried again, and there is no way to replay it from the dashboard. It stays visible in the Webhooks tab so you can see what was missed. An outage shorter than that window costs you nothing; an outage longer than it means those events never arrive, which is why the reconciliation below is not optional.Funds are not at risk here: webhooks are notifications, not settlement, and money sent to a one-time pay-to address can only ever move into your pool. But silence is not proof of settlement. Some outcomes emit no webhook at all —
underpaid, wrong_token, and, if you run payer screening in enforce mode, held_sanctioned. In each of those the funds are still sitting at the pay-to address rather than in your pool, and each needs action from you; see Edge cases. They do appear as rows in Payments and in the status API. The one case that appears nowhere is a payment arriving at an address whose order has already settled — we stop watching it, so there is no row and no webhook. Coming A dedicated Unsettled view is designed and not yet built; see the Roadmap.Reconciliation
Don’t rely on webhooks alone. Two backstops worth building:Poll for stragglers
For orders still pending after a sensible window, call the status API with the intent’s
depositIntentId.Reconcile periodically
Compare your paid orders against the dashboard’s ledger. Any gap is a webhook you missed.
Debugging
The dashboard’s Webhooks tab shows recent deliveries with response codes and bodies. Start there — most failures are a signature mismatch caused by a parsed body, or a timeout from inline work.Signature verification
The most common source of rejected deliveries.