GoCardless · event: payments / confirmed ·
content type: application/json
This is a representative sample — fake IDs, real structure. To see a payload with your data, point the provider at a capture URL (button below).
One click creates a free capture bin with this exact payload already in it — pretty-printed, headers inspectable, replayable to your own endpoint:
Then paste the bin's URL into GoCardless's webhook settings to capture a real delivery. No signup.
content-type: application/json webhook-signature: 5b528dadeeaaa876142437628cda70d8afea0b4fdc915995b6452ee0b1eb86fb origin: https://api.gocardless.com
{
"events": [
{
"id": "EV0123FN9GJ0Q2",
"created_at": "2026-08-30T09:41:26.510Z",
"resource_type": "payments",
"action": "confirmed",
"links": {
"payment": "PM00A9V3N2KQ8D"
},
"details": {
"origin": "gocardless",
"cause": "payment_confirmed",
"description": "Enough time has passed since the payment was submitted for the banks to return an error, so this payment is now confirmed."
},
"metadata": {}
},
{
"id": "EV0123FN9H7T5X",
"created_at": "2026-08-30T09:41:26.510Z",
"resource_type": "payments",
"action": "confirmed",
"links": {
"payment": "PM00A9V3P1XW2R"
},
"details": {
"origin": "gocardless",
"cause": "payment_confirmed",
"description": "Enough time has passed since the payment was submitted for the banks to return an error, so this payment is now confirmed."
},
"metadata": {}
}
],
"meta": {
"webhook_id": "WB0002ZKQW9GJF"
}
}
Webhook-Signature is a bare hex HMAC-SHA256 of the raw body — no prefix,
no timestamp — keyed with the per-endpoint secret from the GoCardless Dashboard (here
gc_wh_sample_secret_R7pXv2Kq9TzL). That's the plain generic scheme: verify
it in the signature debugger (Generic
HMAC-SHA256), or set scheme "Generic" + header name webhook-signature on a
capture bin for live ✓/✗ badges.2xx = accepted; 498 Token Invalid =
signature failed — logged and not retried; 204 No Content
= event type not recognised — also not retried. Any other non-2xx gets
retried. Returning 500 on unknown event types (a common default) causes days of
pointless redelivery; the documented answer is 204-and-ignore, because new event types
are not considered a breaking change.event.id, never on
meta.webhook_id. Delivery is at-least-once and one webhook
batches up to 250 events. webhook_id identifies the
delivery attempt — a retry of the same events arrives under a fresh
webhook_id, so keying idempotency on it processes everything twice.
Events can also arrive out of order (confirmed before the
created it follows): fetch the resource's current state from the API
rather than replaying the event sequence, and branch on the normalised
details.cause, not the bank-specific reason_code.2xx immediately, and process asynchronously. Every
attempt (and a manual-retry button) is visible for 3 months under Developers →
Webhooks in the Dashboard.Origin header distinguishes live
(https://api.gocardless.com) from sandbox
(https://api-sandbox.gocardless.com) deliveries. Webhooks come from three
static IPs (35.204.73.47, 35.204.191.250, 35.204.214.181 — two weeks' notice before
changes), and your endpoint must serve HTTPS with the full certificate chain —
a missing intermediate cert fails delivery even though browsers shrug it off.Reproduce this delivery against any endpoint (your handler, a bin, staging):
$ curl -X POST https://your-endpoint.example/hook \
-H 'content-type: application/json' \
-H 'webhook-signature: 5b528dadeeaaa876142437628cda70d8afea0b4fdc915995b6452ee0b1eb86fb' \
-H 'origin: https://api.gocardless.com' \
-d '{
"events": [
{
"id": "EV0123FN9GJ0Q2",
"created_at": "2026-08-30T09:41:26.510Z",
"resource_type": "payments",
"action": "confirmed",
"links": {
"payment": "PM00A9V3N2KQ8D"
},
"details": {
"origin": "gocardless",
"cause": "payment_confirmed",
"description": "Enough time has passed since the payment was submitted for the banks to return an error, so this payment is now confirmed."
},
"metadata": {}
},
{
"id": "EV0123FN9H7T5X",
"created_at": "2026-08-30T09:41:26.510Z",
"resource_type": "payments",
"action": "confirmed",
"links": {
"payment": "PM00A9V3P1XW2R"
},
"details": {
"origin": "gocardless",
"cause": "payment_confirmed",
"description": "Enough time has passed since the payment was submitted for the banks to return an error, so this payment is now confirmed."
},
"metadata": {}
}
],
"meta": {
"webhook_id": "WB0002ZKQW9GJF"
}
}'