Webhooks
A webhook is how a payment watch tells you something happened without you asking. Every delivery is signed, and the signature is the only thing that makes it worth acting on.
What is delivered here
Payment events only. When a watch you opened detects a payment, settles it, or reaches the finality policy you chose, that is delivered.
Arbitrary event subscriptions are not available on this deployment: they need the Data plane, which is not attached. A subscription request is refused with that reason rather than accepted and never fired.
Verifying a delivery
Every delivery carries a signature header. The algorithm is HMAC-SHA256 over a payload built from the timestamp, the delivery id and the raw body:
signature = hex(HMAC-SHA256(secret, timestamp + "." + delivery_id + "." + body))
Sign over the raw bytes. Parsing the JSON and re-serialising it changes key order and whitespace, and the signature will not match. Keep the body you received.
Check the timestamp too
A signature proves the body came from StoneReason. It does not prove when. Reject a delivery whose timestamp is far from now, or a replay of last week’s event is as valid as today’s.
Compare in constant time
Use your language’s constant-time comparison. A byte-by-byte comparison that exits early on a signature is an oracle.
Rotating a signing secret
A rotation gives you a window where both the old and the new secret verify. Accept either during the overlap, then the old one stops. That is what lets you roll a receiver without dropping a delivery.
Retries
A delivery that does not get a 2xx is retried with a bounded, jittered backoff, and after the last attempt it goes to a dead letter rather than being retried for ever. Jitter matters: without it every failed delivery to a receiver that has just come back arrives at the same instant.
One broken destination does not starve another tenant’s deliveries. The queue is round-robin across projects, and the same project is not always first.
Writing a receiver
- Return 2xx quickly. Acknowledge, then do the work. A receiver that finishes its processing before replying turns a slow database into a retry storm.
- Be idempotent. A delivery can arrive twice — that is what at-least-once means. Key on the delivery id.
- Verify before parsing. An unverified body is somebody else’s input.
Limits
How many endpoints a project may hold is on Limits.