Webhooks
Webhooks let SecurePayAPI notify your server in real time as a transaction moves through its lifecycle — from the initial payment, through settlement, and on to any later refunds or disputes — so you can fulfill orders, update your records, or alert a customer without polling.
Set up an endpoint
- Build an HTTPS endpoint on your server that accepts
POSTrequests. - Add its URL in the Developer section of your dashboard.
SecurePayAPI will start posting events to that URL right away.
When webhooks fire
A webhook is sent on every status change of a transaction — through initiation and 3-D Secure, payment and settlement, and any later refunds or disputes. You keep receiving events until the transaction reaches a final state. See the full list under Transaction statuses.
Payload
Each webhook is a JSON POST describing the transaction's current state:
{
"created": 1717000000,
"uuid": "a1b2c3d4-…",
"id": "abcdef0123456789abcdef01",
"famt": 20,
"currency": "usd",
"externalid": "order_123",
"customerid": "cus_8842",
"status": 16,
"statustext": "PAYING",
"statushistory": [
{ "status": 15, "statustext": "AUTH3DSRESULT" },
{ "status": 16, "statustext": "PAYING" }
]
}
| Field | Description |
|---|---|
created | When the transaction was created, in Unix seconds |
uuid / id | Transaction identifiers |
famt | Payment amount, in the currency's major units (e.g. 20 = $20.00) |
currency | Currency code |
externalid | The identifier you set when creating the payment |
customerid | Your customer identifier |
status | Current status code — see Transaction statuses |
statustext | Name of the current status |
statushistory | Array of { status, statustext } — status changes bundled since the last webhook |
challenge | 3-D Secure challenge data — present only when a challenge occurred |
auth3ds | 3-D Secure authentication data — present only when available |
To keep the number of calls down, several rapid status changes may be delivered in a single webhook — the intermediate states are listed in statushistory.
Transaction statuses
Each webhook carries a numeric status code and its statustext name.
Payment
| Code | Status | Meaning |
|---|---|---|
| 0 | UNPAID | Created, not yet paid |
| 10 | INIT | Payment initiated |
| 11 | DDC | Device data collection (3-D Secure) |
| 12 | AUTH3DS | 3-D Secure authentication started |
| 13 | AUTH3DSCHALLENGE | 3-D Secure challenge required |
| 14 | AUTH3DSCHALLENGEFORM | Challenge form presented |
| 15 | AUTH3DSRESULT | Authentication result received |
| 16 | PAYING | Payment is being processed |
| 1 | PAID | Payment succeeded |
| 3 | FAILED | Payment failed |
| 5 | CANCELED | Payment canceled |
Settlement
| Code | Status | Meaning |
|---|---|---|
| 19 | SETTLEMENTPENDING | Awaiting settlement |
| 20 | SETTLED | Funds settled |
Refunds & holds
| Code | Status | Meaning |
|---|---|---|
| 8 | FROZEN | Funds held for review |
| 34 | REFUNDPENDING | Refund in progress |
| 9 | REFUNDED | Payment refunded |
Disputes
Sent throughout the dispute lifecycle:
| Code | Status | Meaning |
|---|---|---|
| 21 | INFORMATIONREQUESTED | Issuer requested more information |
| 22 | INFORMATIONRESPONDED | Information supplied |
| 23 | INFORMATIONEXPIRED | Information request expired |
| 24 | CHARGEBACKOPEN | Chargeback opened |
| 25 | CHARGEBACKREVERSED | Chargeback reversed |
| 26 | CHARGEBACKWON | Chargeback won |
| 27 | CHARGEBACKLOST | Chargeback lost |
| 28 | PREARBITRATIONOPEN | Pre-arbitration opened |
| 29 | PREARBITRATIONWON | Pre-arbitration won |
| 30 | PREARBITRATIONLOST | Pre-arbitration lost |
| 31 | SCHEMEARBITRATIONOPEN | Scheme arbitration opened |
| 32 | SCHEMEARBITRATIONWON | Scheme arbitration won |
| 33 | SCHEMEARBITRATIONLOST | Scheme arbitration lost |
Acknowledge receipt
Return HTTP 204 as soon as you've stored the event. A 204 confirms delivery and stops further redelivery. If your endpoint returns anything else — or times out — SecurePayAPI retries.
Acknowledge first, process later. Return 204 quickly, then run any heavy work (order fulfillment, emails) asynchronously so the delivery doesn't time out.
Retries
If a delivery isn't acknowledged with 204, it's retried on an escalating schedule:
| Attempt | Wait before retry |
|---|---|
| 1 | 5 seconds |
| 2 | 5 seconds |
| 3 | 10 seconds |
| 4 | 30 seconds |
| 5 | 60 seconds |
| 6 | 10 minutes |
| 7 | 30 minutes |
| 8 | 30 minutes |
| 9+ | 1 hour |
Verify the signature
When your account has an API secret set, every request carries two headers so you can confirm it genuinely came from SecurePayAPI:
| Header | Description |
|---|---|
X-Timestamp | Current time in seconds, rounded down |
X-Signature | An HMAC-SHA256 signature of the request |
Recompute the signature with your secret key and compare it to X-Signature:
const crypto = require('crypto');
function isValidWebhook(req, apiSecret) {
const timestamp = req.headers['x-timestamp'];
const expected = crypto
.createHmac('sha256', apiSecret)
.update(timestamp + JSON.stringify(req.body))
.digest('hex');
return expected === req.headers['x-signature'];
}
Reject any request whose signature doesn't match.
Always verify the signature before trusting a webhook. Don't act on an event you can't authenticate.
Allowlist our IP
Webhook requests are sent from 157.230.218.195. If your infrastructure filters inbound traffic, allow this address.