Webhooks Reference#
Webhooks are HTTP POST requests that GoCardless sends to your server when events occur in your account. Each request contains a batch of one or more Event objects. For a step-by-step guide to receiving and processing webhooks see Stay up to date with webhooks.
Setting up a webhook endpoint#
Register a webhook endpoint from Developers > Webhooks in the GoCardless Dashboard. Each endpoint has its own secret, which is used to sign the requests GoCardless sends to it.
Your endpoint URL must use HTTPS. GoCardless requires the full TLS certificate chain, including intermediate certificates. You can validate your server's certificate chain with Qualys SSL Labs.
Delivery behaviour#
At least once delivery#
GoCardless guarantees that each event will be delivered at least once — it does not guarantee exactly-once delivery. In failure and retry scenarios, the same event may appear in more than one webhook. Your handler must be idempotent: check whether you have already processed each event ID before acting on it.
Out-of-order delivery#
Webhooks may arrive out of order. A payment.confirmed event may arrive before the payment.created event it logically follows. When you receive a webhook, always fetch the current state of the resource from the API rather than inferring it from the event sequence.
Unknown events#
GoCardless may add new event types without considering this a breaking change. If you receive an event type your code does not recognise, return 204 No Content and ignore it — do not return an error, as that would cause GoCardless to retry the webhook unnecessarily.
Determining what to do#
Use the details.cause field on each event to determine how to handle it. The cause is GoCardless's normalised, scheme-independent key for what triggered the event. Avoid branching on details.reason_code — it is bank-specific and inconsistent across schemes.
Processing a webhook#
The recommended flow for handling an incoming webhook:
- Verify the signature (see below). Return
498immediately if invalid. - Respond with
2xxas quickly as possible — within 10 seconds. - Store the raw webhook body in durable storage (database or queue).
- Process each event asynchronously in a background job:
- Check whether you have already processed the event ID.
- Fetch the current resource state from the API.
- Act on the event.
Status codes#
Return one of these status codes from your webhook endpoint:
| Code | When to return |
|---|---|
2xx (e.g. 200 OK) | Webhook received and accepted. |
498 Token Invalid | Signature verification failed. GoCardless will log this and not retry. |
204 No Content | Event type is not recognised. GoCardless will not retry. |
Any other non-2xx response causes GoCardless to retry the webhook.
Retries#
If your endpoint returns a non-2xx response or times out, GoCardless retries automatically:
- 9 total delivery attempts (1 initial + 8 retries).
- Retries occur at increasing intervals after each failure.
- All delivery attempts and outcomes are visible in the GoCardless Dashboard under Developers > Webhooks.
- You can manually trigger a retry from the Dashboard.
Request format#
Webhooks are sent as POST requests with a Content-Type: application/json body. Each request includes:
| Header | Value |
|---|---|
Content-Type | application/json |
Webhook-Signature | HMAC SHA256 hex digest of the request body |
Origin | https://api.gocardless.com (live) or https://api-sandbox.gocardless.com (sandbox) |
Use the Origin header to distinguish live from sandbox webhooks.
Signature verification#
GoCardless signs every webhook using an HMAC SHA256 hex digest of the raw request body, keyed with your webhook endpoint secret. The digest is sent in the Webhook-Signature header.
To verify a webhook:
- Retrieve your webhook endpoint secret from the GoCardless Dashboard.
- Compute
HMAC-SHA256(secret, raw_request_body)as a hex string. - Compare the result to the
Webhook-Signatureheader value. - If they match, the webhook is authentic. If not, return
498 Token Invalid.
Important:
- Always verify the signature before reading or acting on the payload.
- Use the raw request body — do not parse the JSON and re-serialise it, as this may change the byte sequence and break the digest.
- Each webhook endpoint has its own secret. If you have multiple endpoints, verify each with the correct secret.
- Returning
200for an invalid signature would cause GoCardless to treat the webhook as successfully delivered. Returning400would cause unnecessary retries. Use498.
Dashboard history#
Webhooks from the past 3 months are visible in the GoCardless Dashboard under Developers > Webhooks. You can inspect individual delivery attempts, view the payload, and manually retry failed webhooks.
The meta.webhook_id in the webhook payload corresponds to the most recent delivery attempt shown in the Dashboard — useful for debugging, but not for deduplication.
IP addresses#
GoCardless sends webhooks from these static IP addresses. Add them to your firewall allowlist if your infrastructure restricts inbound traffic by source IP.
| IP Address | |
|---|---|
35.204.73.47 | |
35.204.191.250 | |
35.204.214.181 |
GoCardless will give at least 2 weeks' advance notice before adding or removing any IP addresses.
What's next#
Step-by-step guide to building a webhook handler with code samples.
Full reference for the Event object and all resource event types.
Send test webhook events from the GoCardless Dashboard.
Guidance on IP allowlisting for API and webhook traffic.