Skip to content

Webhook events

Every event has the same envelope:

{
"id": "evt_8c1f…",
"type": "payment_intent.succeeded",
"livemode": false,
"created": 1790000000,
"data": { }
}
Field
id Unique per event. The same event delivered twice has the same id.
type One of the events below.
livemode false for test-mode events. Your test and live endpoints are separate, so each only receives its own mode’s events.
created Unix time, in seconds.
data Depends on type.

Events are signed with the Stack-Signature header. See Fulfil orders with webhooks.

A payment succeeded. Fulfil the order.

{
"id": "pi_Lb_-_wULEDdFYYJT",
"amount": "570000",
"currency": "NGN",
"method": "card",
"stack_fee": "2850",
"metadata": { "orderId": "ord_123" }
}
Field
id The payment intent.
amount Kobo, as a string.
currency "NGN"
method balance, card, debit or transfer.
stack_fee Stack’s fee on this payment, in kobo.
metadata What you set when you created it.

An attempt to pay didn’t go through, for example a declined card. The payment is still open: the customer can try again in the sheet, and a later payment_intent.succeeded can follow.

{
"id": "pi_Lb_-_wULEDdFYYJT",
"method": "card",
"last_error": "Declined by the bank.",
"retryable": true
}
Field
id The payment intent.
method What the customer tried.
last_error Why it failed, in words you can show.
retryable true: the same payment can still be paid.

Send test event in the dashboard sends a payment_intent.succeeded whose data is { "test": true, "note": "Sent from the Stack dashboard." }. Answer it with a 2xx and don’t fulfil anything.