Webhooks
Register endpoints in the merchant dashboard under Settings → Webhooks, and subscribe each one to the events it cares about. Endpoints belong to a mode: a sandbox endpoint hears nothing about live orders, so a test receiver can be pointed at a laptop without any risk of it seeing real ones.
Every delivery is a POST with this body:
{
"id": "evt_9Xk2mQpR7vLzT4hB1nWsY6dF3jCg",
"type": "contract.paid",
"created": 1786512000,
"livemode": false,
"data": { "object": { "…": "…" } }
}
id identifies the event, not the delivery: it is the same across retries
and across every endpoint subscribed to it, so it is what to deduplicate on.
livemode says which half of the account produced the event — false for
everything that happened in sandbox.
| Header | Meaning |
|---|---|
ShotPay-Event-Id |
Matches id in the body. |
ShotPay-Event-Type |
Matches type in the body. |
ShotPay-Delivery-Attempt |
1 on the first try, higher on a retry. |
ShotPay-Signature |
t={unix},v1={hex} — see Signatures. |
Answer 2xx as soon as the event is stored. Anything else is retried with
backoff, up to five attempts, so slow processing should happen after the
response rather than before it.
What data.object holds depends on the event — see Event Types for
the map and the fields of each payload.