# GoCardless Developer Documentation > Full content of all documentation pages for LLM consumption. > Index: https://docs.gocardless.com/llms.txt > API reference: https://docs.gocardless.com/docs/api-reference > OpenAPI spec: https://docs.gocardless.com/openapi-schema-public.json --- # Getting Started ## Getting Started URL: https://docs.gocardless.com/docs/getting-started > Find the right integration path for your GoCardless use case. Quick start guides, bank payment fundamentals, and API security. # Getting Started Follow this section to go from zero to a working GoCardless integration. Each guide builds on the previous one, taking you from account setup through to a production-ready payment flow. ## What you'll build By the end of this section you will have a GoCardless sandbox account configured, have made your first authenticated API request, created a payment, set up webhook notifications to track payment events, and completed the steps required to go live. > **Tip: Start in the sandbox** > All guides in this section use the GoCardless sandbox environment. The sandbox is free, requires > no approval, and lets you test the full payment lifecycle without moving real money. You will > switch to the live environment in the Go-live Checklist. ## Guides #### [Set Up](/docs/getting-started/set-up) Create your GoCardless sandbox account, generate API credentials, and configure your development environment. #### [Send Your First API Request](/docs/getting-started/send-your-first-api-request) Authenticate with the GoCardless API and make your first request using your sandbox credentials. #### [Create a Payment](/docs/getting-started/create-a-payment) Create a customer, set up a mandate, and collect a one-off or recurring bank payment end to end. #### [Stay Up to Date with Webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) Subscribe to payment events and handle webhook notifications to keep your system in sync with GoCardless. #### [Go-live Checklist](/docs/getting-started/go-live-checklist) Review the requirements and complete the steps needed to move your integration from sandbox to production. ## Create a Payment URL: https://docs.gocardless.com/docs/getting-started/create-a-payment > Understand payment types, Billing Requests, and how bank-to-bank payments work with GoCardless. # Create a payment ## Create your first payment This page gives you an overview of the payment types we support and introduces Billing Requests, our fastest way of creating and managing payments. > **Info: What you** > - A GoCardless Sandbox account and your API access token ([set up guide](/docs/getting-started/set-up)) > - A developer environment capable of making requests to the GoCardless API ## Payment types We specialise in bank payments and offer several types of payment: - **Recurring and one-off payments via Direct Debit**: This is the most flexible way to collect payments. Your customers complete a mandate, then you can collect payments as agreed with the customer. - **One-off payments via Pay By Bank**: This is the fastest way to collect payments, with confirmation of collection within minutes of the customer giving authorisation. However, it requires authorisation from the payer each time. - **Instant first payment and Direct Debit mandate set up**: This allows you to take an instant first payment while setting up a mandate to take subsequent payments. ## Using Billing Requests to create payments The simplest way to create any payment is with a Billing Request. A Billing Request brings all the parts of a payment together. It combines the customer, their authorisation, their bank details, and the payment details into a single, manageable object. Using them makes it easy to handle everything from recurring payments to one-off payments. They also offer access to our latest open banking payments (Pay By Bank) and products. ## How to create payments #### [Create mandates to collect ad-hoc one-off or recurring payments](/docs/collect-payments/setting-up-mandates) Collect customers' bank details for future payments. #### [Instant one-off payments](/docs/collect-payments/one-off-payments/pay-by-bank) Collect a one-time payment much faster than the typical Direct Debit timeline. #### [First instant payment and mandate set up](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) Take a first-time instant payment (e.g. joining fee) with a mandate set up for subsequent payments. ## Next steps #### [Stay up to date with webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) Receive real-time notifications from GoCardless when things happen in your account. ## Go-live Checklist URL: https://docs.gocardless.com/docs/getting-started/go-live-checklist > Use this checklist to take your GoCardless integration live — from testing to production. # Go-live checklist Use this checklist to take your integration live. Work through each step to ensure a smooth transition from sandbox to production. > **Tip: Before you begin** > Make sure you've completed the previous guides: [Set up](/docs/getting-started/set-up), [Send your > first API request](/docs/getting-started/send-your-first-api-request), [Create a > payment](/docs/getting-started/create-a-payment), and [Stay up to date with > webhooks](/docs/getting-started/stay-up-to-date-with-webhooks). ## Checklist There are common paths you should make sure your integration handles successfully, for example, a customer cancelling their mandate or a payment failing due to lack of funds. #### [Scenario simulators](/docs/developer-resources/scenario-simulators) Replicate various states and responses to test how your integration handles edge cases. #### [Test bank details](/docs/developer-resources/test-bank-details) Use these test bank details to trigger specific payment outcomes in sandbox. Create your live GoCardless accountto start processing real payments. If you are working with a GoCardless Account Executive, they will help you with this step. Just as you did with your sandbox account, navigate to the Developers tab, then select Createfollowed by Create Access Token. Make sure the token has read/writepermissions. > **Warning: Keep your token safe** > Save the token in a secure place or add it directly to your build. You will not be > able to view it again after creation. Update your existing integration to point to the live environment by changing the base URL from https://api-sandbox.gocardless.comto https://api.gocardless.com. If you're using a client library, change the environment setting from sandboxto live. Add a webhook endpoint to your live account following the same steps you completed for sandbox. See the Stay up to date with webhooks guide if you need a refresher. Check that you're still able to successfully make a call to the live API — choose a call that you've already tested in sandbox. Subscribe to API status notifications for both sandbox and live environments. This helps you stay proactively aware of any scheduled maintenance or downtime. ), }, Developers tab, then select Createfollowed by Create Access Token. Make sure the token has read/writepermissions. Be sure to save it in a secure place or add it directly to your build. > **Warning: Keep your token safe** > You will not be able to view the token again after creation. Create your Payment Pages in accordance with our compliance guides. This will need to be approved by a member of our Compliance Team before you can process real payments. > **Info: Compliance review required** > Your custom payment pages must pass a compliance review before going live. Plan for > this in your launch timeline. Update your existing integration to point to the live environment by changing the base URL from https://api-sandbox.gocardless.comto https://api.gocardless.com. If you're using a client library, change the environment setting from sandboxto live. Add a webhook endpoint to your live account following the same steps you completed for sandbox. See the Stay up to date with webhooks guide if you need a refresher. Check that you're still able to successfully make a call to the live API — choose a call that you've already tested in sandbox. Subscribe to API status notifications for both sandbox and live environments. This helps you stay proactively aware of any scheduled maintenance or downtime. ), }, ]} /> ## Next steps #### [Partner integrations](/docs/partner-integrations) Looking to go live with a partner integration? Follow the partner-specific go-live checklist. #### [Explore add-ons](/docs/optimise/prevent-fraud-with-protect-plus) Prevent fraud with Protect+ and reduce failed payments with Success+. #### [FAQs](https://gocardless.com/faq/merchants/developer-api/) Any questions? Read through our most frequently asked questions. ## Send Your First API Request URL: https://docs.gocardless.com/docs/getting-started/send-your-first-api-request > Create your first Billing Request and payment link in the GoCardless sandbox — in under 5 minutes. # Send your first API request ### Create your first test payment authorisation in 5 minutes We'll walk you through making your first API requests by creating and completing a Billing Request, which allows customers to securely authorise payments. > **Info: What you** > - A GoCardless Sandbox account and your API access token ([set up guide](/docs/getting-started/set-up)) > - A developer environment capable of making requests to the GoCardless API ## Creating a billing request A Billing Request enables you to collect all types of GoCardless payments. For now, we'll handle a recurring, direct debit (mandate) request. ### 01. Create your first billing request Copy your access token from the Developers page in the GoCardless dashboard. ```bash ACCESS_TOKEN="your_access_token_here" ``` Create your first billing request by sending the request below. ```http POST https://api.gocardless.com/billing_requests HTTP/1.1 Content-Type: application/json { "billing_requests": { "mandate_request": { "scheme": "bacs" } } } HTTP/1.1 201 Created Location: /billing_requests/BRQ123 Content-Type: application/json { "billing_requests": { "id": "BRQ123", "created_at": "2023-03-22T15:20:08.397Z", "status": "pending", "mandate_request": { "currency": "GBP", "scheme": "bacs", "links": {} }, ... } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/billing_requests" \ -d @- << EOF { "billing_requests": { "mandate_request": { "scheme": "bacs" } } } EOF ``` ```php $client = new \GoCardlessPro\Client([ 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $client->billingRequests()->create([ "params" => [ "mandate_request" => [ "scheme" => "bacs" ] ] ]); ``` ```python import gocardless_pro client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.create(params={ "mandate_request": { "scheme": "bacs" } }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) billing_request = @client.billing_requests.create( params: { mandate_request: { scheme: "bacs" } } ) ``` ```java import static com.gocardless.GoCardlessClient.Environment.SANDBOX; String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests().create() .withMandateRequestScheme("bacs") .execute(); ``` ```nodejs import { GoCardlessClient } from "gocardless-nodejs/client"; import constants from "gocardless-nodejs/constants"; export const client = new GoCardlessClient( process.env.GOCARDLESS_ACCESS_TOKEN, constants.Environments.Sandbox, ); const billingRequest = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var mandateRequest = new GoCardless.Services.BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs", }; var resp = await gocardless.BillingRequests.CreateAsync( new GoCardless.Services.BillingRequestCreateRequest() { MandateRequest = mandateRequest, } ); GoCardless.Resources.BillingRequest billingRequest = resp.BillingRequest; ``` ```go package main import ( gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCreateParams := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } billingRequest, err := client.BillingRequests.Create(context, billingRequestCreateParams) ``` ```ios import GoCardlessSDK let billingRequest = BillingRequest( mandateRequest: MandateRequest(scheme: "bacs") ) GoCardlessSDK.shared.billingRequestService.createBillingRequest(billingRequest: billingRequest) .receive(on: DispatchQueue.main) .sink(receiveCompletion: { completion in if case let .failure(error) = completion { print("Failed to create billing request: \(error)") } }) { createdBillingRequest in let billingRequestId = createdBillingRequest.id print("Successfully created billing request with ID: \(billingRequestId)") } .store(in: &subscriptions) ``` ```android import com.gocardless.gocardlesssdk.GoCardlessSDK import com.gocardless.gocardlesssdk.model.BillingRequest import com.gocardless.gocardlesssdk.model.MandateRequest import com.gocardless.gocardlesssdk.network.ApiError import com.gocardless.gocardlesssdk.network.ApiSuccess import com.gocardless.gocardlesssdk.network.Environment import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking GoCardlessSDK.initSDK( "YOUR_ACCESS_TOKEN", Environment.Sandbox ) val billingRequest = BillingRequest( mandateRequest = MandateRequest(scheme = "bacs") ) runBlocking { // In a real app, use a scope like viewModelScope launch { val result = GoCardlessSDK.billingRequestService.createBillingRequest(billingRequest) when (result) { is ApiSuccess -> { val createdBillingRequest = result.value val billingRequestId = createdBillingRequest.id println("Successfully created billing request with ID: $billingRequestId") } is ApiError -> { println("Failed to create billing request: ${result.error.message}") } } } } ``` > **Tip: Save the billing request ID** > Make a note of the billing request ID returned in the response (e.g. `BRQ123`). You'll need it to > create a payment link in the next step. ### 02. Create your payment link Creating a Billing Request Flow, powered by GoCardless hosted payment pages, generates an authorisation link for collecting payments. ```http POST https://api.gocardless.com/billing_request_flows HTTP/1.1 Content-Type: application/json { "billing_request_flows": { "links": { "billing_request": "your_billing_request_id" } } } HTTP/1.1 201 Created Location: /billing_request_flows/BRF123456 Content-Type: application/json { "billing_request_flows": { "id": "BRF123456", "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=BRF123456", "links": { "billing_request": "BRQ123" }, ... } } ``` ```bash BRQ_ID="your_billing_request_id" curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ "https://api.gocardless.com/billing_request_flows" \ -d @- << EOF { "billing_request_flows": { "links": { "billing_request": "$BRQ_ID" } } } EOF ``` ```php $client = new \GoCardlessPro\Client([ 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $client->billingRequestFlows()->create([ "params" => [ "links" => [ "billing_request" => "your_billing_request_id" ] ] ]); ``` ```python import gocardless_pro client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_request_flows.create(params={ "links": { "billing_request": "your_billing_request_id" } }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_request_flows.create( params: { links: { billing_request: "your_billing_request_id", } } ) ``` ```java import static com.gocardless.GoCardlessClient.Environment.SANDBOX; String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create() .withLinksBillingRequest("your_billing_request_id") .execute(); ``` ```nodejs const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequestFlow = await client.billingRequestFlows.create({ links: { billing_request: "your_billing_request_id", }, }); ``` ```net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequestFlows.CreateAsync( new GoCardless.Services.BillingRequestFlowCreateRequest() { Links = new gocardless.BillingRequestFlowCreateRequest.BillingRequestFlowLinks { BillingRequest = "your_billing_request_id", }, } ); GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow; ``` ```go package main import ( gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams{ Links: gocardless.BillingRequestFlowCreateParamsLinks{ BillingRequest: "your_billing_request_id", }, } billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams) } ``` ```ios import GoCardlessSDK GoCardlessSDK.initSDK(accessToken: "YOUR_ACCESS_TOKEN", environment: .sandbox) { print("GoCardless SDK is initialised") } let billingRequestFlow = BillingRequestFlow( links: Links(billingRequest: "your_billing_request_id") ) GoCardlessSDK.shared.billingRequestFlowService.createBillingRequestFlow(billingRequestFlow: billingRequestFlow) .receive(on: DispatchQueue.main) .sink(receiveCompletion: { completion in switch completion { case let .failure(error): print("API error: \(error)") self.state = .error case .finished: break } }) { createdFlow in self.state = .success(flow: createdFlow) } .store(in: &subscriptions) ``` ```android import com.gocardless.gocardlesssdk.GoCardlessSDK import com.gocardless.gocardlesssdk.model.BillingRequestFlow import com.gocardless.gocardlesssdk.model.Links import com.gocardless.gocardlesssdk.network.ApiError import com.gocardless.gocardlesssdk.network.ApiSuccess import com.gocardless.gocardlesssdk.network.Environment import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking GoCardlessSDK.initSDK( accessToken = "YOUR_ACCESS_TOKEN", environment = Environment.SANDBOX ) val billingRequestFlow = BillingRequestFlow( links = Links(billingRequest = "YOUR_BILLING_REQUEST_ID") ) runBlocking { // In a real app, use a scope like viewModelScope launch { val result = GoCardlessSDK.billingRequestFlowService.createBillingRequestFlow(billingRequestFlow) when (result) { is ApiSuccess -> { val createdFlow = result.value println("Successfully created flow: ${createdFlow.id}") } is ApiError -> { val error = result.error println("API error: ${error.message}") } } } } ``` Copy the `authorisation_url` from the response — you can share this with customers to complete the billing request via a button on your website, SMS, email, or any other channel. ### 03. Customer completes billing request You can now act as your customer would. Go to the authorisation link and enter the details. > **Warning: Sandbox only** > Do not use real customer email addresses or banking information in the Sandbox environment. > Payments will not be processed but email notifications may still be triggered. For testing purposes, use sort code **200000** and account number **55779911** to complete the billing request. ![Customer completing the billing request flow](/images/docs/getting-started/send-your-first-api-request/customer-completes-billing-request.png) ### 04. View your first customer You should now be able to see your newly created customer on the customers page in the dashboard. ![Your first customer on the GoCardless dashboard](/images/docs/getting-started/send-your-first-api-request/customer.png) ## Next steps #### [Create a payment](/docs/getting-started/create-a-payment) Create your first test payment using the mandate you just set up. #### [Partner integrations](/docs/partner-integrations) Accept bank payments directly within your software. Connect to your users' GoCardless accounts with OAuth 2.0. ## Set Up URL: https://docs.gocardless.com/docs/getting-started/set-up > Set up your GoCardless sandbox account, get your API access token, and configure your client library. # Set up This guide covers all the essential steps to prepare for your integration with the GoCardless API. You'll learn the basics of the API, create a sandbox account, and configure your client to make requests. ## Overview The GoCardless API makes it easy to collect bank payments from your customers' bank accounts. With one integration, you can collect payments from the UK, Eurozone, Sweden, Denmark, Australia, New Zealand, Canada, and the United States. Our API has two main functions: #### [Collect payments](/docs/collect-payments) Collect recurring payments via Direct Debit or take instant, one-off payments through open banking schemes, like the UK's Faster Payments service. #### [Send payments](/docs/send-money) Send secure payouts to customers, suppliers, or third parties from a funded payment account. Payments use instant payment rails where available and include security checks like Confirmation of Payee. We also have a range of developer tools to help you with your integration. The rest of this guide will focus on using one of our [client libraries](/docs/developer-resources/client-libraries) to make requests. > **Tip: Other ways to get started** > - The GoCardless [Postman collection](/docs/developer-resources/postman-collection) is available to try out our APIs. > - The [GoCardless CLI](/docs/developer-resources/gc-cli) is a developer tool to help you build, test and manage your integration directly from your terminal. ## Step-by-step guide ### 1. Get your sandbox access token GoCardless has two environments: a free **Sandbox** for testing and **Live** for processing real payments. Each environment is completely separate, with its own account, dashboard, access tokens, and API URLs. For this guide, we will only use the Sandbox environment. A dedicated testing environment to build your integration without moving real money. SettingValueDashboardmanage-sandbox.gocardless.comAPI Base URLhttps://api-sandbox.gocardless.com/), }, , ]} /> To start, you will need a read-write access token from your Sandbox account. - [ ] **Sign up for a Sandbox account**: Create one in [Sandbox](https://manage-sandbox.gocardless.com/sign-up) if you haven't already. - [ ] **Create an access token**: In your Sandbox dashboard, go to the **Developers** tab and select **Create access token**. Give your token a name and choose **Read-Write** access. - [ ] **Copy your token**: Click the **Copy** button and save the token somewhere safe. For security, you will not be able to view it again. > **Warning: Keep your token safe** > Your access token grants full API access. Never commit it to source control or share it publicly. > Store it in an environment variable or a secrets manager. ### 2. Set up your client Now it's time to set up your application to communicate with the GoCardless API. You have two options: Our client libraries handle boilerplate code, authentication, and request signing for you. We recommend using a library if one is available for your language. Official librariesLanguagePackagePythongocardless_proJavagocardless-pro-java Gogocardless-pro-goRubygocardless_proNode.jsgocardless-nodejsPHPgocardless-pro-php.NETGoCardlessiOSGoCardlessSDKAndroidgocardless-pro-android-sdk ), }, , ]} /> #### Install and initialise Install the library using your package manager, then initialise the client with your sandbox access token. ```php composer require gocardless/gocardless-pro ``` ```python pip install gocardless_pro ``` ```ruby gem install gocardless_pro ``` ```java com.gocardless gocardless-pro LATEST ``` ```nodejs npm install gocardless-nodejs ``` ```net dotnet add package GoCardless ``` ```go go get github.com/gocardless/gocardless-pro-go/v6 ``` ```curl export GC_ACCESS_TOKEN="your_access_token_here" # Example: list customers curl -H "Authorization: Bearer $GC_ACCESS_TOKEN" \ -H "GoCardless-Version: 2015-07-06" \ https://api-sandbox.gocardless.com/customers ``` ```php getenv("GC_ACCESS_TOKEN"), "environment" => \GoCardlessPro\Environment::SANDBOX, ]); ``` ```python import os import gocardless_pro client = gocardless_pro.Client( access_token=os.environ["GC_ACCESS_TOKEN"], environment="sandbox" ) ``` ```ruby require "gocardless_pro" client = GoCardlessPro::Client.new( access_token: ENV["GC_ACCESS_TOKEN"], environment: :sandbox ) ``` ```java import com.gocardless.GoCardlessClient; GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); ``` ```nodejs const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); ``` ```net using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); ``` ```go import gocardless "github.com/gocardless/gocardless-pro-go/v6" accessToken := os.Getenv("GC_ACCESS_TOKEN") client, err := gocardless.New(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) ``` ### 3. You're ready to go! You have now configured your client and are ready to make your first API request. ## Next steps #### [Send your first API request](/docs/getting-started/send-your-first-api-request) Create and collect your first test payment authorisation. #### [Create a payment](/docs/getting-started/create-a-payment) Understand payment types, Billing Requests, and how bank-to-bank payments work. ## Stay Up to Date with Webhooks URL: https://docs.gocardless.com/docs/getting-started/stay-up-to-date-with-webhooks > Learn about API authentication, webhook signatures, and securing your GoCardless integration. # Stay up to date with webhooks A webhook is a request that GoCardless sends to your server to alert you of an event. Adding support for webhooks allows you to receive real-time notifications from GoCardless when things happen in your account, so you can take automated actions in response. - When a payment fails due to lack of funds, retry it automatically. - When a customer cancels their mandate with the bank, suspend their account. - When a subscription generates a new payment, record it against their account. ## Create a webhook endpoint To start receiving webhooks, add a webhook endpoint from your [Sandbox Dashboard](https://manage-sandbox.gocardless.com/developers/webhook-endpoints). ![Creating a webhook endpoint in the GoCardless dashboard](/images/docs/getting-started/stay-up-to-date-with-webhooks/create_webhook_endpoint.png) Enter the HTTPS URL where your webhook handler will be available, give your endpoint a name, and click **"Create webhook endpoint"**. Then click on your new endpoint in the list and **copy the secret to your clipboard**. ## Build a webhook handler Webhooks are HTTP POST requests made to the URL you provided, with a JSON body. Here's an example: ```http POST https://example.com/webhooks HTTP/1.1 User-Agent: gocardless-webhook-service/1.1 Content-Type: application/json Webhook-Signature: 78e3507f61f141046969c73653402cb50b714f04322da04d766ee0f6d2afe65f { "events": [ { "id": "EV123", "created_at": "2014-08-04T12:00:00.000Z", "action": "cancelled", "resource_type": "mandates", "links": { "mandate": "MD123", "organisation": "OR123" }, "details": { "origin": "bank", "cause": "bank_account_disabled", "description": "Your customer closed their bank account.", "scheme": "bacs", "reason_code": "ADDACS-B" } } ] } ``` > **Info: For Partners** > The body contains one or more events (up to a maximum of 250), specifying the type of the resource > affected (e.g. "mandates" or "payments"), its ID, the ID of the organisation the resource belongs > to (which you stored when obtaining their access token) and the action that occurred (e.g. > "cancelled" or "expired"). ### Secure your webhooks The first step when you receive a webhook is to check its signature — this ensures it's genuinely from GoCardless and hasn't been forged. A signature is provided in the `Webhook-Signature` header. Compute the signature yourself using the POST body and your webhook endpoint secret, then compare it to the header value. If they match, the webhook is genuine. Keep the secret safe and change it periodically using the Dashboard. ```php handlePost( @RequestHeader("Webhook-Signature") String signatureHeader, @RequestBody String requestBody) { String webhookEndpointSecret = System.getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET"); try { List events = Webhook.parse(requestBody, signatureHeader, webhookEndpointSecret); for (Event event : events) { // Process the event } return new ResponseEntity("OK", HttpStatus.OK); } catch(InvalidSignatureException e) { return new ResponseEntity("Incorrect Signature", HttpStatus.BAD_REQUEST); } } } ``` ```nodejs const process = require("process"); const webhooks = require("gocardless-nodejs/webhooks"); const webhookEndpointSecret = process.env.WEBHOOK_ENDPOINT_SECRET; // Handle the incoming Webhook and check its signature. const parseEvents = ( eventsRequestBody, signatureHeader, // From webhook header ) => { try { return webhooks.parse(eventsRequestBody, webhookEndpointSecret, signatureHeader); } catch (error) { if (error instanceof webhooks.InvalidSignatureError) { console.log("invalid signature, look out!"); } } }; ``` ```net [HttpPost] public ActionResult HandleWebhook() { var requestBody = Request.InputStream; requestBody.Seek(0, System.IO.SeekOrigin.Begin); var requestJson = new StreamReader(requestBody).ReadToEnd(); // We recommend storing your webhook endpoint secret in an environment variable // for security var secret = ConfigurationManager.AppSettings["GoCardlessWebhookSecret"]; var signaure = Request.Headers["Webhook-Signature"] ?? ""; try { foreach (Event event in WebhookParser.Parse(requestJson, secret, signature)) { // Process the event } return new HttpStatusCodeResult(HttpStatusCode.OK); } catch (InvalidSignatureException e) { return new HttpStatusCodeResult(HttpStatusCode.Forbidden); } } ``` ```go package main import ( "http" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { http.HandleFunc("/webhookEndpoint", func(w http.ResponseWriter, r *http.Request) { wh, err := NewWebhookHandler("secret", EventHandlerFunc(func(event gocardless.Event) error { parseEvent(event) })) wh.ServeHTTP(w, r) }) } func parseEvents(event gocardless.Event) { // work through list of events } ``` ### Processing events A webhook can contain multiple events, each with a `resource_type` (e.g. "payments" or "mandates"), an `action` (e.g. "cancelled"), and `details` (specifying why the event happened). You can see a full list of possible combinations in the [event types reference](/docs/api-reference/events/mandate). Here's an example handler for when a mandate is cancelled: ```php action) { case "cancelled": print("Mandate " . $event->links->mandate . " has been cancelled!\n"); // You should keep some kind of record of what events have been processed // to avoid double-processing // // $event = Event::where("gocardless_id", $event->id)->first(); // You should perform processing steps asynchronously to avoid timing out if // you receive many events at once. To do this, you could use a queueing // system like Beanstalkd CancelServiceAndNotifyCustomer::performAsynchronously($event->links->mandate); break; default: print("Don't know how to process a mandate " . $event->action . " event\n"); break; } } // We recommend storing your webhook endpoint secret in an environment variable // for security $webhook_endpoint_secret = getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET"); $request_body = file_get_contents('php://input'); $headers = getallheaders(); $signature_header = $headers["Webhook-Signature"]; try { $events = \GoCardlessPro\Webhook::parse( $request_body, $signature_header, $webhook_endpoint_secret ); foreach ($events as $event) { print("Processing event " . $event->id . "\n"); switch ($event->resource_type) { case "mandates": process_mandate_event($event); break; default: print("Don't know how to process an event with resource_type " . $event->resource_type . "\n"); break; } } header("HTTP/1.1 200 OK"); } catch (\GoCardlessPro\Core\Exception\InvalidSignatureException $e) { header("HTTP/1.1 498 Invalid Token"); } ``` ```python # Here, we're using a Django view, but essentially the same code will work in # other Python web frameworks (e.g. Flask) with minimal changes import os import logging from django.views.generic import View from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator from django.http import HttpResponse from gocardless_pro import webhooks, Client from gocardless_pro.errors import InvalidSignatureError from myinvoicingapp.models import GoCardlessEvent # Handle the incoming Webhook and perform an action with the Webhook data. class Webhook(View): logger = logging.getLogger(**name**) @method_decorator(csrf_exempt) def dispatch(self, *args, **kwargs): return super(Webhook, self).dispatch(*args, **kwargs) def post(self, request, *args, **kwargs): try: for event in self._get_events(request): self.process(event) return HttpResponse(204) except InvalidSignatureError: return HttpResponse(498) def is_already_processed(event): return GoCardlessEvent.objects.filter(gocardless_id=event.id).exists() def process(self, event): self.logger.info("Processing event {}\n".format(event.id)) if self.is_already_processed(event): return if event.resource_type == 'mandates': return self.process_mandate_event(event) # ... Handle other resource types else: self.logger.info("Don't know how to process an event with \ resource_type {}\n".format(event.resource_type)) def process_mandate_event(self, event): access_token = os.environ('GOCARDLESS_ACCESS_TOKEN') client = Client( access_token=access_token, environment='sandbox' ) mandate = client.mandates.get(event.id) if event.action == 'cancelled': # You should perform processing steps asynchronously to avoid timing out # if you receive many events at once. To do this, you could use a # queueing system like RQ (https://github.com/ui/django-rq) self.logger.info("Mandate {} has been cancelled\n".format(mandate.id)) # ... Handle other mandate actions else: self.logger.info("Don't know how to process an event with \ resource_type {}\n".format(event.resource_type)) GoCardlessEvent.objects.create(gocardless_id=mandate.id) def _get_events(self, request): secret = os.environ['GC_WEBHOOK_SECRET'] signature = request.META["HTTP_WEBHOOK_SIGNATURE"] body = request.body.strip() return webhooks.parse(body, secret, signature) ``` ```ruby require 'gocardless_pro' class MandateEventProcessor def self.process(event, response) case event.action when 'cancelled' response.stream.write("Mandate #{event.links.mandate} has been cancelled\n") # You should keep some kind of record of what events have been processed # to avoid double-processing, checking if the event already exists before # event = Event.find_by(gocardless_id: event['id']) # You should perform processing steps asynchronously to avoid timing out # if you receive many events at once. To do this, you could use a # queueing system like # Resque (https://github.com/resque/resque) # # Once you've performed the actions you want to perform for an event, you # should make a record to avoid accidentally processing the same one twice # CancelServiceAndNotifyCustomer.enqueue(event['links']['mandate']) else response.stream.write("Don't know how to process a mandate #{event.action} " \ "event\n") end end end def create # We recommend storing your webhook endpoint secret in an environment variable # for security webhook_endpoint_secret = ENV['GOCARDLESS_WEBHOOK_ENDPOINT_SECRET'] # In a Rack app (e.g. Sinatra), access the POST body with # `request.body.tap(&:rewind).read` request_body = request.raw_post # In a Rack app (e.g. Sinatra), the header is available as # `request.env['HTTP_WEBHOOK_SIGNATURE']` signature_header = request.headers['Webhook-Signature'] begin events = GoCardlessPro::Webhook.parse(request_body: request_body, signature_header: signature_header, webhook_endpoint_secret: webhook_endpoint_secret) events.each do |event| # We're using Rails's streaming functionality here to write directly to the # response rather than using views, as one would usually. response.stream.write("Processing event #{event.id}\n") case event.resource_type when 'mandates' MandateEventProcessor.process(event, response) else response.stream.write("Don't know how to process an event with resource_type " \ "#{event.resource_type}\n") end end response.stream.close render status: 200 rescue GoCardlessPro::Webhook::InvalidSignatureError render status: 498 end end ``` ```java package hello; // Use the POM file at // https://raw.githubusercontent.com/gocardless/gocardless-pro-java-maven-example/master/pom.xml import com.gocardless.errors.InvalidSignatureException; import com.gocardless.resources.Event; import com.gocardless.Webhook; import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.http.ResponseEntity; @RestController public class HelloController { private String processMandate(Event event) { /* You should keep some kind of record of what events have been processed to avoid double-processing, checking if the event already exists before processing it. You should perform processing steps asynchronously to avoid timing out if you receive many events at once. To do this, you could use a queueing system like @Async. https://spring.io/guides/gs/async-method/ Once you've performed the actions you want to perform for an event, you should make a record to avoid accidentally processing the same one twice */ switch (event.getAction()) { case "cancelled": return "Mandate " + event.getLinks().getMandate() + " has been cancelled.\n"; default: return "Do not know how to process an event with action " + event.getAction() + ".\n"; } } private String processEvent(Event event) { switch (event.getResourceType()) { case MANDATES: return processMandate(event); default: return "Don't know how to process an event of resource_type " + event.getResourceType().toString() + ".\n"; } } @PostMapping("/") public ResponseEntity handlePost( @RequestHeader("Webhook-Signature") String signatureHeader, @RequestBody String requestBody) { String webhookEndpointSecret = System.getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET"); try { List events = Webhook.parse(requestBody, signatureHeader, webhookEndpointSecret); String responseBody = ""; for (Event event : events) { responseBody += processEvent(event); } return new ResponseEntity(responseBody, HttpStatus.OK); } catch(InvalidSignatureException e) { return new ResponseEntity("Incorrect Signature", HttpStatus.BAD_REQUEST); } } } ``` ```nodejs const process = require("process"); const webhooks = require("gocardless-nodejs/webhooks"); const express = require("express"); const bodyParser = require("body-parser"); const app = express(); // parse incoming body of Content-Type of application/json to return it as a plain string which needs to be passed into the webhooks.parse method app.use(bodyParser.text({ type: "application/json" })); const webhookEndpointSecret = process.env.WEBHOOK_ENDPOINT_SECRET; const processMandate = (event) => { /* You should keep some kind of record of what events have been processed to avoid double-processing, checking if the event already exists before processing it. You should perform processing steps asynchronously to avoid timing out if you receive many events at once. To do this, you could use a queueing system like # Bull https://github.com/OptimalBits/bull Once you've performed the actions you want to perform for an event, you should make a record to avoid accidentally processing the same one twice */ switch (event.action) { case "cancelled": return `Mandate ${event.links.mandate} has been cancelled.\n`; default: return `Do not know how to process an event with action ${event.action}`; } }; const processEvent = (event) => { switch (event.resource_type) { case "mandates": return processMandate(event); default: return `Do not know how to process an event with resource_type ${event.resource_type}`; } }; app.post("/", async (req, res) => { const eventsRequestBody = req.body; const signatureHeader = req.headers["Webhook-Signature"]; // Handle the incoming Webhook and check its signature. const parseEvents = ( eventsRequestBody, signatureHeader, // From webhook header ) => { try { return webhooks.parse(eventsRequestBody, webhookEndpointSecret, signatureHeader); } catch (error) { if (error instanceof webhooks.InvalidSignatureError) { console.log("invalid signature, look out!"); } } }; try { const events = parseEvents(eventsRequestBody, signatureHeader); let responseBody = ""; for (const event of events) { responseBody += processEvent(event); } res.send(responseBody); } catch (error) { res.status(400).send({ error: error.message }); } }); app.listen(process.env.PORT, () => { console.log(`server started on port: ${process.env.PORT}`); }); ``` ```net [HttpPost] public ActionResult HandleWebhook() { var requestBody = Request.InputStream; requestBody.Seek(0, System.IO.SeekOrigin.Begin); var requestJson = new StreamReader(requestBody).ReadToEnd(); // We recommend storing your webhook endpoint secret in an environment variable // for security var secret = ConfigurationManager.AppSettings["GoCardlessWebhookSecret"]; var signature = Request.Headers["Webhook-Signature"]; try { // Webhooks can contain many events. In a real implementation, you should handle // the processing of each event asychronously to avoid timing out here. // You could check whether you've processed the event before (by recording the event // ID when you process it) and retrieve the associated resource to ensure that you have // the most up-to-date information about it. foreach (GoCardless.Resources.Event event in WebhookParser.Parse(requestJson, secret, signature)) { // To keep this example simple, we're only handling Mandate events if (event.ResourceType == GoCardless.Resources.EventResourceType.Mandates) { switch (event.Action) { case "created": Console.WriteLine($"Mandate {event.Links.Mandate} has been created, yay!"); break; case "cancelled": Console.WriteLine($"Oh no, mandate {event.Links.Mandate} was cancelled!"); break; default: Console.WriteLine($"{event.Links.Mandate} has been {event.Action}"); break; } } else { Console.WriteLine($"No method to handle {event.ResourceType} events yet"); } } return new HttpStatusCodeResult(HttpStatusCode.OK); } catch (InvalidSignatureException e) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } } ``` ```go package main import ( "fmt" "http" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { processMandateEvent := func(event gocardless.Event) { /* You should keep some kind of record of what events have been processed to avoid double-processing, checking if the event already exists before processing it. You should perform processing steps asynchronously to avoid timing out if you receive many events at once. To do this, you could dispatch each event to a worker pool of goroutines, or push it onto a queueing system such as Amazon SQS or RabbitMQ. Once you've performed the actions you want to perform for an event, you should make a record to avoid accidentally processing the same one twice */ switch event.Action { case "cancelled": fmt.Println("Mandate " + event.Links.Mandate + " has been cancelled.\n") default: fmt.Println("Do not know how to process an event with action " + event.Action + ".\n") } } parseEvent := func(event gocardless.Event) { switch event.getResourceType() { case "mandates": processMandateEvent(event) default: fmt.Println("Don't know how to process an event of resource_type " + event.ResourceType + ".\n") } } http.HandleFunc("/webhookEndpoint", func(w http.ResponseWriter, r *http.Request) { wh, err := gocardless.NewWebhookHandler("secret", gocardless.EventHandlerFunc(func(event gocardless.Event) error { parseEvent(event) })) wh.ServeHTTP(w, r) }) } ``` Send a test webhook and click on it in the list. You'll see a response like this: ```http Processing event EVTEST8XP9DCPK Mandate index_ID_123 has been cancelled! ``` We'll send webhooks exactly like this when real events happen in your account. You can add support for as many `resource_type`s and `action`s as you like, using all of the [event data](/docs/api-reference/events/payment) we provide. ## Test your webhook handler #### [Dashboard](https://manage-sandbox.gocardless.com/developers/webhooks/create) Use the **"Send test webhook"** feature. Select your endpoint, set the resource type to `mandates` and the action to `cancelled`, then click send. #### [GoCardless CLI](/docs/developer-resources/gc-cli) Use the `gc` CLI to locally test webhook integrations. Trigger events and forward them to your server's webhook handler directly from the terminal. #### [Scenario Simulator](/docs/developer-resources/scenario-simulators) In the **sandbox environment**, use scenario simulators to manually trigger specific cases. Available in the Developer section of the dashboard and through the API. ### Advanced: Using TLS client authentication Using TLS enables us to encrypt data in transit. Additional security can be achieved by using client authentication alongside server authentication. Client authentication adds an extra check in the TLS handshake to validate that the client is authorised to access the endpoint — confirming that it is GoCardless making the request, not a malicious entity. To authorise GoCardless to send webhooks, provide a valid certificate and private key issued by your certificate authority. In practice, this can be a self-signed certificate. Useful instructions for generating certificates can be found in the [CoreOS documentation](https://github.com/coreos/docs/blob/master/os/generate-self-signed-certificates.md), using Cloudflare's [cfssl](https://github.com/cloudflare/cfssl) toolkit. > **Info: Certificate requirements** > We only support RSA keypairs. We recommend setting a long lifetime for the certificate to avoid > unnecessary management overhead. Both certificate and key must be provided in base64-encoded PEM > format. Enter the certificate and key into the webhook endpoint form in the developers section of the GoCardless dashboard. All subsequent requests will be client-authenticated. ![Webhook client certificate configuration](/images/docs/getting-started/stay-up-to-date-with-webhooks/webhook_client_certificate.png) ## Next steps #### [Go-live checklist](/docs/getting-started/go-live-checklist) Review the requirements and complete the steps needed to move your integration from sandbox to production. --- # Collect Payments ## Collect Payments URL: https://docs.gocardless.com/docs/collect-payments > Overview of collecting payments with GoCardless. # Collect Payments GoCardless specialises in bank payments, offering flexible solutions for both recurring and one-off payments. Whether you're collecting subscription fees, taking one-time purchases, or setting up payment plans, we provide the tools to accept payments directly from your customers' bank accounts. Before you start building, there are two things to decide: which payment type fits your use case, and how you want to integrate. > **Info: New: GoCardless Components (Bacs mandate setup)** > If you're setting up Bacs Direct Debit mandates only and want a fully embedded, brand-matched experience without the build effort of a custom integration, GoCardless Components is worth a look. It's a JavaScript library that drops the mandate setup flow directly into your page, with customisable styling, validation, and error handling out of the box. > > [Learn more →](/docs/collect-payments/integration-types/gocardless-components) ## 1. What payment type(s) do you need? | Payment Type | How it Works | Best For | Availability | | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------- | | [One-off Direct Debit](/docs/collect-payments/one-off-payments/one-off-direct-debit) | Highly flexible — collect payments on an ad-hoc basis with varying amounts, frequency, and/or timing as agreed with the customer. | Usage-based billing, invoices, variable charges | All schemes (Bacs, SEPA, ACH, BECS, PAD, Autogiro, Betalingsservice, PayTo) | | [Subscriptions](/docs/collect-payments/recurring-payments) | Fixed amount collected automatically at regular intervals. | Subscriptions, memberships, SaaS | All schemes | | [Instalments](/docs/collect-payments/recurring-payments/instalment-schedules) | Fixed number of payments spreading the cost of a purchase. | Payment plans, tuition, high-ticket items | All schemes | | [Pay By Bank](/docs/collect-payments/one-off-payments) | One-off payment confirmed within seconds via the customer's banking app — no mandate required. | E-commerce checkouts, time-sensitive or high-value one-off payments | GBP (Faster Payments), EUR (SEPA Instant) | | [Instant + Direct Debit](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) | Immediate instant upfront payment via the customer's bank app, plus a Direct Debit setup for future recurring payments. | Services needing immediate activation + ongoing billing | GBP (Faster Payments + Bacs), EUR (SEPA Instant + SEPA DD) | | [Variable Recurring Payments (Pay By Bank)](/docs/collect-payments/recurring-payments/variable-recurring-payments) | Recurring variable payments via open banking consent. A mandate is required once; merchants can then take future recurring payments and an instant upfront payment. | Sweeping between accounts, loan repayments, investment top-ups | GBP only — restricted to a limited group of sectors | ## 2. How do you want to integrate? The simplest way to create any payment is with a **Billing Request**. A Billing Request brings all the parts of a payment together — the customer, their authorisation, their bank details, and the payment details — into a single, manageable object. All four approaches below are powered by the same underlying Billing Requests API. | | Hosted Payment Pages | Drop-in Flow (JavaScript) | [Components](/docs/collect-payments/integration-types/gocardless-components) | Custom Payment Pages | | --------------------------------- | -------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------- | ---------------------------------- | | **API** | Billing Request Flows | Billing Request Flows | Billing Requests | Billing Requests | | **Integration effort** | Minimal — redirect to GoCardless | Moderate — embed our JS component | Moderate — embed our JS library inline | Significant — build from scratch | | **Hosting** | GoCardless-hosted page | Stays on your site | Integrated into your product | Fully integrated into your product | | **UI** | GoCardless Checkout | Embedded component | Embedded component | Your own UI | | **Customisation** | Low — logo and company name only | Medium — styling to match your brand | High — styling to match your brand | Full — complete control | | **Payment types** | All | Direct Debit only | BACS mandate setup (expanding) | All | | **Mobile responsive** | ✓ | ✓ | ✓ | You build it | | **Multi-language support** | ✓ | ✓ | ✓ | You build it | | **Scheme-appropriate flows** | ✓ | ✓ | BACS (expanding to SEPA and Pay by Bank) | You build it | | **Compliance handled** | ✓ | ✓ | ✓ | You build it, we check it | | **Customer stays on your domain** | — | ✓ | ✓ | ✓ | > **Info:** > If you're unsure where to start, use Hosted Payment Pages — it's the fastest way to go live, and > you can switch to a more custom approach later. ## Understanding bank payments ### Direct Debit vs Pay By Bank Most payment types use Direct Debit: the customer sets up a mandate, and you collect payments against it. Payments take 2–5 business days to confirm, depending on the [scheme and country](https://gocardless.com/legal/payment-timings/). Pay By Bank uses open banking to collect a one-off payment with confirmation within minutes. It doesn't require a mandate but needs customer authorisation each time. ### What is Direct Debit? Direct Debit is a pull-based payment mechanism that puts you in control of collecting payments from your customers, rather than relying on them to send you funds when payment is due. Other common regional terms include Pre-Authorised Debit (or Pre-Auth), or the name of the operator's scheme — such as ACH in the US. Each country (or region) operates its own bank payments scheme with its own rules and regulations. ### What is a scheme? A scheme is the infrastructure and operational mechanism that enables bank-to-bank payments to be processed within a [country or region](https://gocardless.com/guides/posts/bank-debit/#bank-debit-schemes-around-the-world). The scheme a payment is processed through is determined by where the payer's bank account is based. ### Optimising payments [Success+](/docs/optimise/reduced-failed-payments-with-success-plus) automatically recovers failed payments using machine learning. [Protect+](/docs/optimise/prevent-fraud-with-protect-plus) detects and combats fraud using GoCardless payment intelligence data. ## What's next? #### [Integration Planner](/docs/collect-payments/integration-planner) Answer a few questions to get a recommended integration path for your use case. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Collect customers' bank details for future Direct Debit payments. #### [One-off Payments](/docs/collect-payments/one-off-payments) Take a single payment via Pay By Bank or Direct Debit. #### [Recurring Payments](/docs/collect-payments/recurring-payments) Set up subscriptions, instalments, or variable recurring payments. ## Integration Planner URL: https://docs.gocardless.com/docs/collect-payments/integration-planner > Plan your GoCardless payment integration. # Integration Planner Get oriented with the Billing Request — the API that powers all GoCardless payment flows — then choose the integration path that suits your team and use the interactive guide to map out the exact steps you'll need to build. ## Find your billing request steps A Billing Request moves through a defined sequence of steps from creation to completion. Select your integration type to filter the steps to exactly what you need to build. ## The Billing Request API #### What is a Billing Request? A Billing Request helps create resources that require input or action from a customer. This single API supports all geographies and features offered by GoCardless. #### What to use it for Set up a Direct Debit, PayTo, or VRP mandate; take a one-off Pay By Bank via Open Banking; or combine both. #### How it works 1. Create a Billing Request specifying your desired outcome 2. Complete the required actions 3. Use a Billing Request Flow to complete any remaining actions ## Integration paths Pick the approach that fits the level of control you want over the customer experience. #### [Hosted Payment Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) GoCardless handles the full customer UX. Redirect your customer to a GoCardless-hosted page to complete their mandate or payment authorisation, then we redirect them back. **Best for:** Getting live quickly with minimal frontend work. #### [JavaScript Drop-in Flow](/docs/collect-payments/integration-types/javascript-drop-in-flow) Embed a GoCardless-managed modal directly into your page. Customers complete the payment flow without leaving your site, while GoCardless handles the UX inside the drop-in. **Best for:** Keeping customers on your site with minimal integration effort. #### [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) Embed GoCardless-built checkout components into your own checkout. Customers set up their mandate without leaving your page, and you control the layout and styling while GoCardless handles compliance, payer verification and validation for you. **Best for:** Keeping customers on your page with a branded checkout, minimal integration effort and no compliance burden. #### [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages) You own the full customer UX and call the GoCardless API directly at each step. Requires more development effort but gives you complete control over design and flow. **Best for:** Teams with engineering resources who want a fully branded experience. ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Collect customers' bank details for future Direct Debit payments. #### [One-off Payments](/docs/collect-payments/one-off-payments) Take a single payment via Pay By Bank or Direct Debit. #### [Recurring Payments](/docs/collect-payments/recurring-payments) Set up subscriptions, instalments, or variable recurring payments. #### [Billing Request API Reference](/docs/api-reference/billing-request) Full reference for the Billing Requests API. ## One-off Payments URL: https://docs.gocardless.com/docs/collect-payments/one-off-payments > Take a single payment via Pay by Bank or Direct Debit without setting up a mandate. # One-off Payments GoCardless supports two ways to collect a one-off payment without requiring a recurring mandate: - **Pay by Bank** — An instant Open Banking payment where the customer authorises a single transfer from their bank app. Best for immediate, high-value, or first-time payments. - **One-off Direct Debit** — Creates a mandate that is immediately consumed by a single payment. Best when you want the familiar Direct Debit flow but only need to charge once. #### [Pay by Bank](/docs/collect-payments/one-off-payments/pay-by-bank) Collect an instant bank-to-bank payment authorised directly through the customer's banking app. #### [One-off Direct Debit](/docs/collect-payments/one-off-payments/one-off-direct-debit) Set up a single-use mandate and collect a one-off Direct Debit payment. ## Recurring Payments URL: https://docs.gocardless.com/docs/collect-payments/recurring-payments > Set up subscriptions, instalments, or variable recurring payments against an active mandate. # Recurring Payments Once you have an active mandate, GoCardless supports several models for collecting recurring payments: - **Subscriptions** — Fixed amount on a regular schedule (weekly, monthly, etc.). - **Instalment schedules** — A defined series of payments, each with its own amount and date. - **Variable Recurring Payments (VRP)** — Open Banking-powered payments where the amount varies within agreed limits, without re-authorisation for each charge. - **Instant first payment with mandate** — Collect an Open Banking payment immediately while simultaneously setting up a Direct Debit mandate. #### [Subscriptions](/docs/collect-payments/recurring-payments/subscriptions) Collect a fixed amount on a regular schedule against an active mandate. #### [Instalment Schedules](/docs/collect-payments/recurring-payments/instalment-schedules) Define a series of payments with individual amounts and charge dates. #### [Variable Recurring Payments](/docs/collect-payments/recurring-payments/variable-recurring-payments) Collect variable amounts within agreed limits via Open Banking, without re-authorisation. #### [Instant First Payment with Mandate](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) Collect an instant Open Banking payment while setting up a Direct Debit mandate in parallel. ## Setting up Mandates URL: https://docs.gocardless.com/docs/collect-payments/setting-up-mandates > Set up Direct Debit mandates using Billing Requests. # Setting Up Mandates A Direct Debit mandate is an authorisation from your customer that allows you to collect payments directly from their bank account. Once authorised, you can collect recurring or future payments without the customer taking any further action. ## Step-by-step guide ### Create a Billing Request Use Billing Requests to create a mandate alongside a new customer. If you want to create a mandate against an existing customer, specify the customer ID in `links.customer.` Pass currency rather than scheme — GoCardless automatically selects the optimal scheme for that currency. > **Info: Verified Mandates** > If you submit the verify setting, payers may be asked to verify themselves if GoCardless deems > them risky or if scheme compliance requires it. [Read more about verified > mandates.](/docs/collect-payments/setting-up-mandates/verified-mandates) ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->create([ "params" => [ "mandate_request" => [ "scheme" => "bacs" ] ] ]); ``` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.create(params={ "mandate_request": { "scheme": "bacs" } }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.create( params: { mandate_request: { scheme: "bacs" } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests().create() .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequest = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var mandateRequest = new GoCardless.Services.BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs", }; var resp = await gocardless.BillingRequests.CreateAsync( new GoCardless.Services.BillingRequestCreateRequest() { MandateRequest = mandateRequest, } ); GoCardless.Resources.BillingRequest billingRequest = resp.BillingRequest; ``` ```http POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "bacs" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) config, err := gocardless.NewConfig(accessToken, opts) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCreateParams := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } billingRequest, err := client.BillingRequests.Create(context, billingRequestCreateParams) ``` ```CLI gc create billing_request \ -d 'mandate_request[scheme]=bacs' ``` Response: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "payment_request": null, "mandate_request": { "currency": "GBP", "scheme": "bacs" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010PDF4WD", "mandate_request": "MRQ123", "organisation": "OR123" }, "actions": [ { "type": "collect_customer_details", "status": "pending" }, { "type": "collect_bank_account", "status": "pending" } ] } } ``` ### Authorise the mandate Direct the customer to authorise the mandate. How you do this depends on your integration type: - **Hosted Pages:** Create a Billing Request Flow and redirect the customer to the authorisation_url. See the [Hosted Pages guide](/docs/collect-payments/integration-types/gocardless-hosted-pages) - **Drop-in:** Create a Billing Request Flow and pass the flow ID to the GoCardless Drop-in. See the [Drop-in guide](/docs/collect-payments/integration-types/javascript-drop-in-flow) - **Custom Payment Pages:** Collect customer details and bank account via Billing Request actions, then confirm payer details. See the [Custom Payment Pages guide](/docs/collect-payments/integration-types/custom-payment-pages) For Hosted Pages and Drop-in, create the flow: ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequestFlows()->create([ "params" => [ "redirect_uri" => "https://my-company.com/landing", "exit_uri" => "https://my-company.com/exit", "links" => [ "billing_request" => "BRQ000010NMDMH2" ] ] ]); ``` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_request_flows.create(params={ "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_request_flows.create( params: { redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create() .withRedirectUri("https://my-company.com/landing") .withExitUri("https://my-company.com/exit") .withLinksBillingRequest("BRQ000010NMDMH2") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequestFlow = await client.billingRequestFlows.create({ redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequestFlows.CreateAsync( new GoCardless.Services.BillingRequestFlowCreateRequest() { RedirectUri = "https://my-company.com/landing", ExitUri = "https://my-company.com/exit", Links = new GoCardless.Services.BillingRequestFlowCreateRequest.BillingRequestFlowLinks { BillingRequest = "BRQ000010NMDMH2", }, } ); GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow; ``` ```http POST https://api.gocardless.com/billing_request_flows HTTP/1.1 { "billing_request_flows": { "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here"; opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(accessToken, opts) billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams{} billingRequestFlowCreateParams.RedirectUri = "https://my-company.com/landing" billingRequestFlowCreateParams.ExitUri = "https://my-company.com/exit" billingRequestFlowCreateParams.Links.BillingRequest = "BRQ000010NMDMH2" billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams) ``` ```CLI gc create billing_request_flow \ -d "links[billing_request]= BRQ000010NMDMH2" \ -d 'redirect_uri=https://my-company.com/landing' \ -d 'exit_uri=https://my-company.com/exit' ``` Response: ```json { "billing_request_flows": { "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=", "lock_customer_details": false, "lock_bank_account": false, "auto_fulfil": true, "created_at": "2021-03-30T16:23:10.679Z", "expires_at": "2021-04-06T16:23:10.679Z", "redirect_uri": "https://my-company.com/completed", "links": { "billing_request": "BRQ123" } } } ``` `redirect_uri:` where GoCardless sends the customer after they complete the flow. `exit_uri:` where GoCardless sends customers who can't complete the flow (e.g. bank not found, no online banking). We recommend returning them to your checkout so they can choose a different payment method. Send the `authorisation_url` to your customer via redirect, email, or SMS. > **Warning: Confirming Billing Request Flow outcome** > Don't rely on the redirect back to your site to confirm the outcome. Always use webhooks. Learn > more about [Mandate events](/docs/collect-payments/events-and-webhooks/mandate-events). ### Collect payments With the mandate active, you're now ready to collect payments. See: - [One-off payments](/docs/collect-payments/one-off-payments/one-off-direct-debit) - [Recurring payments](/docs/collect-payments/recurring-payments/subscriptions) ### Lock customer details or bank account Set these on the Billing Request Flow to restrict what the customer can change during the flow: | **Parameter** | **Effect** | | ----------------------------- | ---------------------------------------------------------------------- | | `lock_customer_details: true` | Customer details page hidden; customer cannot edit | | `lock_bank_account: true` | The bank selection page is hidden; the customer cannot switch accounts | | `lock_currency: true` | The customer cannot change the currency or payment scheme | If both `lock_customer_details` and lock_bank_account are set, the customer goes directly to the confirmation page. > **Info: New to GoCardless?** > See the [Collect Payments overview](/docs/collect-payments) to choose your payment type and > integration approach before starting this guide. ## What the customer will see ### Customer fills in their personal details Collect customer details in order to complete the billing request. **Note:** this screen is skipped if the details already exist, or the customer details have been locked. ![bacs-collect-customer-details](/images/docs/collect-payments/setting-up-mandates/screenshot_2024-05-12_at_14.45.51.png) ### Customer provides their bank details Provide the Bank account details in order for GC to setup mandate. **Note:** this screen is skipped if the details already exist or the bank account is locked. ![bacs-collect-bank-details](/images/docs/collect-payments/setting-up-mandates/screenshot_2024-05-12_at_14.49.32.png) ### Customer confirms their details Confirm your personal and bank details, before authorising the mandate. ![bacs-confirm-payer-details](/images/docs/collect-payments/setting-up-mandates/screenshot_2024-05-12_at_15.16.36.png) ### Confirmed! View confirmation that the payment has been successful once the bank authorisation is complete. ![bacs-05-success](/images/docs/collect-payments/setting-up-mandates/4.jpg) ## What's next? #### [Verified Mandates](/docs/collect-payments/setting-up-mandates/verified-mandates) Require identity verification for high-risk or scheme-mandated payers. #### [Offline Mandates](/docs/collect-payments/setting-up-mandates/offline-mandates) Import mandates collected outside of GoCardless. #### [One-off Direct Debit](/docs/collect-payments/one-off-payments/one-off-direct-debit) Collect a one-off payment against an existing mandate. #### [Recurring Payments](/docs/collect-payments/recurring-payments/subscriptions) Set up subscription schedules against active mandates. ## Billing Request Purpose Codes URL: https://docs.gocardless.com/docs/collect-payments/scheme-guidance/billing-request-purpose-codes > Purpose codes for billing requests. # Purpose codes for Billing Request ## VRP Commercial Purpose codes | **Values** | **Description** | | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `bonus_payment` | Transaction is the payment of a bonus. | | `cash_management_transfer` | Transaction is a general cash management instruction. | | `card_bulk_clearing` | A service that is settling money for a bulk of card transactions, while referring to a specific transaction file or other information like terminal ID, card acceptor ID or other transaction details. | | `credit_card_payment` | Transaction is related to a payment of credit card. | | `trade_settlement_payment` | Transaction is related to settlement of a trade, eg a foreign exchange deal or a securities transaction. | | `debit_card_payment` | Transaction is related to a payment of debit card. | | `dividend` | Transaction is the payment of dividends. | | `deliver_against_payment` | Code used to pre-advise the account servicer of a forthcoming deliver against payment instruction. | | `epayment` | Transaction is related to ePayment. | | `fee_collection_and_interest` | Transaction is related to the payment of a fee and interest. | | `fee_collection` | A service that is settling card transaction related fees between two parties. | | `person_to_person_payment` | General Person-to-Person Payment. Debtor and Creditor are natural persons. | | `government_payment` | Transaction is a payment to or from a government department. | | `hedging_transaction` | Transaction is related to the payment of a hedging operation. | | `irrevocable_credit_card_payment` | Transaction is reimbursement of credit card payment. | | `irrevocable_debit_card_payment` | Transaction is reimbursement of debit card payment. | | `intra_company_payment` | Transaction is an intra-company payment, ie, a payment between two companies belonging to the same group. | | `interest` | Transaction is the payment of interest. | | `lockbox_transactions` | Transaction is related to identify cash handling via Night Safe or Lockbox by bank or vendor on behalf of a physical store. | | `loan` | Transaction is related to the transfer of a loan to a borrower. | | `commercial` | Mobile P2B Payment | | `consumer` | Mobile P2P Payment | | `other_payment` | Other payment purpose. | | `pension_payment` | Transaction is the payment of pension. | | `represented` | Collection used to re-present previously reversed or returned direct debit transactions. | | `reimbursement_received_credit_transfer` | Transaction is related to a reimbursement for commercial reasons of a correctly received credit transfer. | | `receive_against_payment` | Code used to pre-advise the account servicer of a forthcoming receive against payment instruction. | | `salary_payment` | Transaction is the payment of salaries. | | `securities` | Transaction is the payment of securities. | | `social_security_benefit` | Transaction is a social security benefit, ie payment made by a government to support individuals. | | `supplier_payment` | Transaction is related to a payment to a supplier. | | `tax_payment` | Transaction is the payment of taxes. | | `trade` | Transaction is related to the payment of a trade finance transaction. | | `treasury_payment` | Transaction is related to treasury operations. E.g. financial contract settlement. | | `value_added_tax_payment` | Transaction is the payment of value added tax. | | `with_holding` | Transaction is the payment of withholding tax. | | `cash_management_sweep_account` | Classification: Cash Management. Transaction relates to a cash management instruction, requesting a sweep of the account of the Debtor above an agreed floor amount, up to a target or zero balance. The purpose is to move the funds from multiple accounts to a single bank account. Funds can move domestically or across border and more than one bank can be used. | | `cash_management_top_account` | Classification: Cash Management. Transaction relates to a cash management instruction, requesting to top the account of the Creditor above a certain floor amount, up to a target or zero balance. The floor amount, if not pre-agreed by the parties involved, may be specified. | | `cash_management_zero_balance_account` | Transaction relates to a cash management instruction, requesting to zero balance the account of the Debtor. Zero Balance Accounts empty or fill the balances in accounts at the same bank, in the same country into or out of a main account each day. | | `crossborder_mi_payments` | Transaction to be processed as a domestic payment instruction originated from a foreign bank. | | `foreign_currency_domestic_transfer` | Foreign Currency Transaction that is processed between two domestic financial institutions. | | `cash_in_pre_credit` | Transaction is a direct debit for a cash order of notes and/or coins. | | `cash_out_notes_coins` | Transaction is a direct debit for a cash order of notes and/or coins. | | `carrier_guarded_wholesale_valuables` | Transaction is a payment towards a Party for the collection of cash by the Cash in Transit company. | ## PayTo purpose codes | **Values** | **Description** | | ------------------- | -------------------------- | | `mortgage` | Mortgage Payments | | `utility` | Utility Payments | | `loan` | Loan Payments | | `dependant_support` | Dependant Support Payments | | `gambling` | Gambling Payments | | `retail` | Retail Payments | | `salary` | Salary Payments | | `personal` | Personal Payment | | `government` | Government Payments | | `pension` | Pension Payments | | `tax` | Tax Payments | | `other` | Other Service Payments | ## What's next? #### [VRP Commercial Purpose Codes](/docs/collect-payments/scheme-guidance/vrp-purpose-codes) Browse purpose codes for VRP Commercial payments. #### [Billing Requests API Reference](/docs/api-reference/billing-request) Full reference for creating Billing Requests with purpose codes. #### [PayTo Agreements and Payments](/docs/collect-payments/recurring-payments/payto) Use PayTo purpose codes when setting up mandates in Australia. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates using the Billing Requests API with purpose codes. ## Custom Payment Pages Overview URL: https://docs.gocardless.com/docs/collect-payments/integration-types/custom-payment-pages > Build your own payment flow using the GoCardless API directly. # Custom Payment Pages Build your own payment flow from scratch using the GoCardless API directly. You have complete control over the user experience, design, and logic. **This is the highest-effort integration.** Consider starting with [Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) to validate your integration — the underlying API is identical. If you only need Bacs mandate setup, consider [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) — a pre-built checkout that's white-labelled, upgradeable, and compliant without additional work. Supports: **Direct Debit, Pay By Bank, VRP.** > **Info: Paid add-on required** > Custom Payment Pages require the Fully custom checkout paid add-on. It's enabled in the Sandbox > environment so you can build and test freely, but you'll need to add it to your Live account to > use it for real payments. See [Pricing](https://gocardless.com/pricing) for details. ## Best for - White-label or embedded product requirements - Complex, multi-step user journeys - Deep integration with your application - Full control over UX and brand experience ## How it works - Build your own UI for collecting customer and bank account details - Use the Billing Requests API to create and progress through the payment flow - Call API actions to collect customer details, collect bank account information, and confirm - Handle all states, errors, and edge cases in your application **What you need to handle:** - Input validation and error messaging - Scheme-specific bank account fields per country - Compliance requirements (e.g., Direct Debit Guarantee display) - Loading states and timeouts - Mobile responsiveness ## Step-by-step guide ### Create a billing request The Billing Request defines what you're collecting and applies to all flows. The payload differs by payment type: #### Direct Debit Mandate ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'mandate_request': { 'scheme': 'bacs', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { mandate_request: { scheme: 'bacs' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000301", "status": "pending", "mandate_request": { "scheme": "bacs", "currency": "GBP" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "collect_bank_account", "required": true, "completed": false }, { "type": "confirm_payer_details", "required": true, "completed": false } ] } } ``` #### Pay By Bank ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "payment_request": { "description": "Order #9012", "amount": 12000, "currency": "GBP", "scheme": "faster_payments" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'payment_request' => [ 'description' => 'Order #9012', 'amount' => 12000, 'currency' => 'GBP', 'scheme' => 'faster_payments', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'payment_request': { 'description': 'Order #9012', 'amount': 12000, 'currency': 'GBP', 'scheme': 'faster_payments', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { payment_request: { description: 'Order #9012', amount: 12000, currency: 'GBP', scheme: 'faster_payments' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withPaymentRequestDescription("Order #9012") .withPaymentRequestAmount(12000) .withPaymentRequestCurrency("GBP") .withPaymentRequestScheme("faster_payments") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ payment_request: { description: "Order #9012", amount: 12000, currency: "GBP", scheme: "faster_payments", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { PaymentRequest = new BillingRequestCreateRequest.BillingRequestPaymentRequest { Description = "Order #9012", Amount = 12000, Currency = "GBP", Scheme = "faster_payments" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ PaymentRequest: &gocardless.BillingRequestCreateParamsPaymentRequest{ Description: "Order #9012", Amount: 12000, Currency: "GBP", Scheme: "faster_payments", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000302", "status": "pending", "payment_request": { "amount": 12000, "currency": "GBP", "scheme": "faster_payments" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "select_institution", "required": true, "completed": false }, { "type": "bank_authorisation", "required": true, "completed": false } ] } } ``` #### Direct Debit + Pay By Bank ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "payment_request": { "description": "First payment", "amount": 5000, "currency": "GBP", "scheme": "faster_payments" }, "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'payment_request' => [ 'description' => 'First payment', 'amount' => 5000, 'currency' => 'GBP', 'scheme' => 'faster_payments', ], 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'payment_request': { 'description': 'First payment', 'amount': 5000, 'currency': 'GBP', 'scheme': 'faster_payments', }, 'mandate_request': { 'scheme': 'bacs', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { payment_request: { description: 'First payment', amount: 5000, currency: 'GBP', scheme: 'faster_payments' }, mandate_request: { scheme: 'bacs' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withPaymentRequestDescription("First payment") .withPaymentRequestAmount(5000) .withPaymentRequestCurrency("GBP") .withPaymentRequestScheme("faster_payments") .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ payment_request: { description: "First payment", amount: 5000, currency: "GBP", scheme: "faster_payments", }, mandate_request: { scheme: "bacs", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { PaymentRequest = new BillingRequestCreateRequest.BillingRequestPaymentRequest { Description = "First payment", Amount = 5000, Currency = "GBP", Scheme = "faster_payments" }, MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ PaymentRequest: &gocardless.BillingRequestCreateParamsPaymentRequest{ Description: "First payment", Amount: 5000, Currency: "GBP", Scheme: "faster_payments", }, MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000303", "status": "pending", "payment_request": { "amount": 5000, "currency": "GBP", "scheme": "faster_payments" }, "mandate_request": { "scheme": "bacs", "currency": "GBP" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "collect_bank_account", "required": true, "completed": false }, { "type": "confirm_payer_details", "required": true, "completed": false }, { "type": "select_institution", "required": true, "completed": false }, { "type": "bank_authorisation", "required": true, "completed": false } ] } } ``` #### Variable Recurring Payments (VRP) ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "fallback_enabled": true, "purpose_code": "loan", "payment_context_code": "billing_goods_and_services_in_arrears", "payment_purpose_code": "bank_loan_delayed_draw_funding", "mandate_request": { "scheme": "faster_payments", "constraints": { "start_date": "2024-11-01", "max_amount_per_payment": 50000, "periodic_limits": [{ "period": "month", "max_total_amount": 100000, "alignment": "creation_date" }] } } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'fallback_enabled' => true, 'purpose_code' => 'loan', 'payment_context_code' => 'billing_goods_and_services_in_arrears', 'payment_purpose_code' => 'bank_loan_delayed_draw_funding', 'mandate_request' => [ 'scheme' => 'faster_payments', 'constraints' => [ 'start_date' => '2024-11-01', 'max_amount_per_payment' => 50000, 'periodic_limits' => [ [ 'period' => 'month', 'max_total_amount' => 100000, 'alignment' => 'creation_date', ], ], ], ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'fallback_enabled': True, 'purpose_code': 'loan', 'payment_context_code': 'billing_goods_and_services_in_arrears', 'payment_purpose_code': 'bank_loan_delayed_draw_funding', 'mandate_request': { 'scheme': 'faster_payments', 'constraints': { 'start_date': '2024-11-01', 'max_amount_per_payment': 50000, 'periodic_limits': [ { 'period': 'month', 'max_total_amount': 100000, 'alignment': 'creation_date', }, ], }, }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { fallback_enabled: true, purpose_code: 'loan', payment_context_code: 'billing_goods_and_services_in_arrears', payment_purpose_code: 'bank_loan_delayed_draw_funding', mandate_request: { scheme: 'faster_payments', constraints: { start_date: '2024-11-01', max_amount_per_payment: 50000, periodic_limits: [ { period: 'month', max_total_amount: 100000, alignment: 'creation_date' } ] } } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withFallbackEnabled(true) .withPurposeCode("loan") .withPaymentContextCode("billing_goods_and_services_in_arrears") .withPaymentPurposeCode("bank_loan_delayed_draw_funding") .withMandateRequestScheme("faster_payments") .withMandateRequestConstraintsStartDate("2024-11-01") .withMandateRequestConstraintsMaxAmountPerPayment(50000) .withMandateRequestConstraintsPeriodicLimitsBuilder() .withPeriod("month") .withMaxTotalAmount(100000) .withAlignment("creation_date") .done() .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ fallback_enabled: true, purpose_code: "loan", payment_context_code: "billing_goods_and_services_in_arrears", payment_purpose_code: "bank_loan_delayed_draw_funding", mandate_request: { scheme: "faster_payments", constraints: { start_date: "2024-11-01", max_amount_per_payment: 50000, periodic_limits: [ { period: "month", max_total_amount: 100000, alignment: "creation_date", }, ], }, }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { FallbackEnabled = true, PurposeCode = "loan", PaymentContextCode = "billing_goods_and_services_in_arrears", PaymentPurposeCode = "bank_loan_delayed_draw_funding", MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "faster_payments", Constraints = new BillingRequestCreateRequest.BillingRequestMandateRequestConstraints { StartDate = "2024-11-01", MaxAmountPerPayment = 50000, PeriodicLimits = new List { new BillingRequestCreateRequest.BillingRequestMandateRequestConstraintsPeriodicLimit { Period = "month", MaxTotalAmount = 100000, Alignment = "creation_date" } } } } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } fallbackEnabled := true params := gocardless.BillingRequestCreateParams{ FallbackEnabled: &fallbackEnabled, PurposeCode: "loan", PaymentContextCode: "billing_goods_and_services_in_arrears", PaymentPurposeCode: "bank_loan_delayed_draw_funding", MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "faster_payments", Constraints: &gocardless.BillingRequestCreateParamsMandateRequestConstraints{ StartDate: "2024-11-01", MaxAmountPerPayment: 50000, PeriodicLimits: []gocardless.BillingRequestCreateParamsMandateRequestConstraintsPeriodicLimit{ { Period: "month", MaxTotalAmount: 100000, Alignment: "creation_date", }, }, }, }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000301", "created_at": "2024-11-01T00:00:00.000Z", "status": "pending", "mandate_request": { "scheme": "faster_payments", "currency": "GBP", "verify": "recommended", "consent_type": "recurring", "description": null, "sweeping": false, "payer_requested_dual_signature": false, "metadata": {}, "links": {}, "constraints": { "start_date": "2024-11-01", "end_date": null, "max_amount_per_payment": 50000, "periodic_limits": [ { "period": "month", "max_total_amount": 100000, "alignment": "creation_date", "max_amount_per_period": null, "max_payments": null } ] } }, "payment_request": null, "subscription_request": null, "instalment_schedule_request": null, "metadata": {}, "fallback_enabled": true, "fallback_occurred": false, "purpose_code": "loan", "payment_purpose_code": "bank_loan_delayed_draw_funding", "sign_flow_url": null, "auto_fulfil": false, "actions": [ { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "collect_customer_details": { "default_country_code": "GB", "incomplete_fields": { "customer": ["given_name", "family_name", "email"], "customer_billing_detail": ["address_line1", "city", "postal_code", "country_code"] } } }, { "type": "select_institution", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "institution_guess_status": "pending" }, { "type": "collect_bank_account", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "available_country_codes": ["GB"] }, { "type": "bank_authorisation", "required": true, "completes_actions": [], "requires_actions": ["select_institution", "collect_customer_details"], "status": "pending", "bank_authorisation": { "authorisation_type": "mandate" } }, { "type": "confirm_payer_details", "required": true, "completes_actions": [], "requires_actions": ["collect_customer_details", "collect_bank_account"], "status": "pending" } ], "links": { "mandate_request": "MRQ0000301" } } } ``` ### Collect Customer Details Applies to all flows ```http curl -X POST https://api.gocardless.com/billing_requests/BRQ0000301/actions/collect_customer_details \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "data": { "customer": { "email": "frank.osborne@example.com", "given_name": "Frank", "family_name": "Osborne" }, "customer_billing_detail": { "address_line1": "27 Acer Road", "city": "London", "postal_code": "E8 3GX", "country_code": "GB" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->collectCustomerDetails( 'BRQ0000301', [ 'data' => [ 'customer' => [ 'email' => 'frank.osborne@example.com', 'given_name' => 'Frank', 'family_name' => 'Osborne', ], 'customer_billing_detail' => [ 'address_line1' => '27 Acer Road', 'city' => 'London', 'postal_code' => 'E8 3GX', 'country_code' => 'GB', ], ], ] ); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.collect_customer_details( 'BRQ0000301', params={ 'data': { 'customer': { 'email': 'frank.osborne@example.com', 'given_name': 'Frank', 'family_name': 'Osborne', }, 'customer_billing_detail': { 'address_line1': '27 Acer Road', 'city': 'London', 'postal_code': 'E8 3GX', 'country_code': 'GB', }, } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.collect_customer_details( 'BRQ0000301', data: { customer: { email: 'frank.osborne@example.com', given_name: 'Frank', family_name: 'Osborne' }, customer_billing_detail: { address_line1: '27 Acer Road', city: 'London', postal_code: 'E8 3GX', country_code: 'GB' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCollectCustomerDetailsResponse response = client.billingRequests() .collectCustomerDetails("BRQ0000301") .withCustomerEmail("frank.osborne@example.com") .withCustomerGivenName("Frank") .withCustomerFamilyName("Osborne") .withCustomerBillingDetailAddressLine1("27 Acer Road") .withCustomerBillingDetailCity("London") .withCustomerBillingDetailPostalCode("E8 3GX") .withCustomerBillingDetailCountryCode("GB") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.collectCustomerDetails("BRQ0000301", { data: { customer: { email: "frank.osborne@example.com", given_name: "Frank", family_name: "Osborne", }, customer_billing_detail: { address_line1: "27 Acer Road", city: "London", postal_code: "E8 3GX", country_code: "GB", }, }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CollectCustomerDetailsAsync( "BRQ0000301", new BillingRequestCollectCustomerDetailsRequest { Data = new BillingRequestCollectCustomerDetailsRequest.CollectCustomerDetailsData { Customer = new BillingRequestCollectCustomerDetailsRequest.CustomerData { Email = "frank.osborne@example.com", GivenName = "Frank", FamilyName = "Osborne" }, CustomerBillingDetail = new BillingRequestCollectCustomerDetailsRequest.CustomerBillingDetailData { AddressLine1 = "27 Acer Road", City = "London", PostalCode = "E8 3GX", CountryCode = "GB" } } } ); ``` ```go package main "context" "fmt" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCollectCustomerDetailsParams{ Data: gocardless.BillingRequestCollectCustomerDetailsParamsData{ Customer: gocardless.BillingRequestCollectCustomerDetailsParamsCustomer{ Email: "frank.osborne@example.com", GivenName: "Frank", FamilyName: "Osborne", }, CustomerBillingDetail: gocardless.BillingRequestCollectCustomerDetailsParamsCustomerBillingDetail{ AddressLine1: "27 Acer Road", City: "London", PostalCode: "E8 3GX", CountryCode: "GB", }, }, } result, err := client.BillingRequests.CollectCustomerDetails(context.TODO(), "BRQ0000301", params) if err != nil { panic(err) } fmt.Println(result) ``` **Response:** Billing Request with collect_customer_details marked completed. ### Collect a bank account Applies to all flows. Required fields vary by country and scheme. Example for UK (Bacs / Faster Payments): ```http curl -X POST https://api.gocardless.com/billing_requests/BRQ0000301/actions/collect_bank_account \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "data": { "country_code": "GB", "account_holder_name": "Frank Osborne", "account_number": "55779911", "branch_code": "200000" } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->collectBankAccount( 'BRQ0000301', [ 'data' => [ 'country_code' => 'GB', 'account_holder_name' => 'Frank Osborne', 'account_number' => '55779911', 'branch_code' => '200000', ], ] ); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.collect_bank_account( 'BRQ0000301', params={ 'data': { 'country_code': 'GB', 'account_holder_name': 'Frank Osborne', 'account_number': '55779911', 'branch_code': '200000', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.collect_bank_account( 'BRQ0000301', data: { country_code: 'GB', account_holder_name: 'Frank Osborne', account_number: '55779911', branch_code: '200000' } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCollectBankAccountResponse response = client.billingRequests() .collectBankAccount("BRQ0000301") .withCountryCode("GB") .withAccountHolderName("Frank Osborne") .withAccountNumber("55779911") .withBranchCode("200000") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.collectBankAccount("BRQ0000301", { data: { country_code: "GB", account_holder_name: "Frank Osborne", account_number: "55779911", branch_code: "200000", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CollectBankAccountAsync( "BRQ0000301", new BillingRequestCollectBankAccountRequest { Data = new BillingRequestCollectBankAccountRequest.CollectBankAccountData { CountryCode = "GB", AccountHolderName = "Frank Osborne", AccountNumber = "55779911", BranchCode = "200000" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCollectBankAccountParams{ Data: gocardless.BillingRequestCollectBankAccountParamsData{ CountryCode: "GB", AccountHolderName: "Frank Osborne", AccountNumber: "55779911", BranchCode: "200000", }, } result, err := client.BillingRequests.CollectBankAccount(context.TODO(), "BRQ0000301", params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** Billing Request with collect_bank_account marked completed. ### Confirm payer details Applies to: **all flows including mandates** (Mandate-only flow and Payment + Mandate flow The customer confirms their consent to set up the mandate. No request body required. ```http curl -X POST https://api.gocardless.com/billing_requests/BRQ0000301/actions/confirm_payer_details \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->confirmPayerDetails('BRQ0000301'); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.confirm_payer_details('BRQ0000301') ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.confirm_payer_details('BRQ0000301') ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestConfirmPayerDetailsResponse response = client.billingRequests() .confirmPayerDetails("BRQ0000301") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.confirmPayerDetails("BRQ0000301"); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.ConfirmPayerDetailsAsync("BRQ0000301"); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } result, err := client.BillingRequests.ConfirmPayerDetails(context.TODO(), "BRQ0000301", gocardless.BillingRequestConfirmPayerDetailsParams{}) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** Billing Request with collect_bank_account marked completed. ```json { "billing_requests": { "id": "BRQ0000301", "status": "ready_to_fulfil", "actions": [ { "type": "collect_customer_details", "required": true, "completed": true }, { "type": "collect_bank_account", "required": true, "completed": true }, { "type": "confirm_payer_details", "required": true, "completed": true } ] } } ``` ### Select Institution Applies to: **all flows including payments** (Payment-only flow and Payment + Mandate flow Identify the customer's bank for the open banking authorisation. Use the list institutions endpoint to present a bank picker to the customer. ```http curl -X POST https://api.gocardless.com/billing_requests/BRQ0000302/actions/select_institution \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "data": { "institution": "MONZO_MONZGB2L", "country_code": "GB" } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->selectInstitution( 'BRQ0000302', [ 'data' => [ 'institution' => 'MONZO_MONZGB2L', 'country_code' => 'GB', ], ] ); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.select_institution( 'BRQ0000302', params={ 'data': { 'institution': 'MONZO_MONZGB2L', 'country_code': 'GB', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.select_institution( 'BRQ0000302', data: { institution: 'MONZO_MONZGB2L', country_code: 'GB' } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestSelectInstitutionResponse response = client.billingRequests() .selectInstitution("BRQ0000302") .withInstitution("MONZO_MONZGB2L") .withCountryCode("GB") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.selectInstitution("BRQ0000302", { data: { institution: "MONZO_MONZGB2L", country_code: "GB", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.SelectInstitutionAsync( "BRQ0000302", new BillingRequestSelectInstitutionRequest { Data = new BillingRequestSelectInstitutionRequest.SelectInstitutionData { Institution = "MONZO_MONZGB2L", CountryCode = "GB" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestSelectInstitutionParams{ Data: gocardless.BillingRequestSelectInstitutionParamsData{ Institution: "MONZO_MONZGB2L", CountryCode: "GB", }, } result, err := client.BillingRequests.SelectInstitution(context.TODO(), "BRQ0000302", params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** Billing Request with select_institution marked completed. ### Create a bank authorisation Applies to: **all flows including payments** (Payment-only flow and Payment + Mandate flow. ```http curl -X POST https://api.gocardless.com/bank_authorisations \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "bank_authorisations": { "redirect_uri": "https://yoursite.com/payment-complete", "links": { "billing_request": "BRQ0000302" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->bankAuthorisations()->create([ 'params' => [ 'redirect_uri' => 'https://yoursite.com/payment-complete', 'links' => [ 'billing_request' => 'BRQ0000302', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.bank_authorisations.create( params={ 'redirect_uri': 'https://yoursite.com/payment-complete', 'links': { 'billing_request': 'BRQ0000302', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.bank_authorisations.create( params: { redirect_uri: 'https://yoursite.com/payment-complete', links: { billing_request: 'BRQ0000302' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BankAuthorisationCreateResponse response = client.bankAuthorisations() .create() .withRedirectUri("https://yoursite.com/payment-complete") .withLinksBuilder() .withBillingRequest("BRQ0000302") .done() .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.bankAuthorisations.create({ redirect_uri: "https://yoursite.com/payment-complete", links: { billing_request: "BRQ0000302", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BankAuthorisations.CreateAsync( new BankAuthorisationCreateRequest { RedirectUri = "https://yoursite.com/payment-complete", Links = new BankAuthorisationCreateRequest.BankAuthorisationLinks { BillingRequest = "BRQ0000302" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BankAuthorisationCreateParams{ RedirectUri: "https://yoursite.com/payment-complete", Links: gocardless.BankAuthorisationCreateParamsLinks{ BillingRequest: "BRQ0000302", }, } result, err := client.BankAuthorisations.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "bank_authorisations": { "id": "BAU0000101", "url": "https://pay.gocardless.com/obauth/BAU0000101", "redirect_uri": "https://yoursite.com/payment-complete", "expires_at": "2024-06-01T18:15:00.000Z", "links": { "billing_request": "BRQ0000302" } } } ``` ### Redirect customer to their bank Applies to: **all flows including payments** (Payment-only flow and Payment + Mandate flow Redirect your customer to the url from the bank authorisation response. The customer approves the payment in their banking app, then is returned to your redirect_uri. > **Warning:** > Don't use the redirect to confirm the outcome. Always use webhooks. ### Fulfill the billing request Applies to: **Mandate-only flow** Once the Billing Request status is ready_to_fulfil, call the fulfil action to activate the mandate. ```http curl -X POST https://api.gocardless.com/billing_requests/BRQ0000301/actions/fulfil \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->fulfil('BRQ0000301'); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.fulfil('BRQ0000301') ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.fulfil('BRQ0000301') ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestFulfilResponse response = client.billingRequests() .fulfil("BRQ0000301") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.fulfil("BRQ0000301"); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.FulfilAsync("BRQ0000301"); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } result, err := client.BillingRequests.Fulfil(context.TODO(), "BRQ0000301", gocardless.BillingRequestFulfilParams{}) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000301", "status": "fulfilled", "links": { "mandate_request_mandate": "MD0000301" } } } ``` ### Handle Webhooks | **Event** | **Meaning** | **Applies to** | | -------------------------- | --------------------------- | ------------------------------- | | billing_requests.fulfilled | Billing Request completed | All flows | | mandates.active | Mandate is active and ready | Mandate-only, payment + mandate | | payments.confirmed | Pay By Bank payment settled | Payment-only, payment + mandate | | payments.failed | Payment failed | Payment-only, payment + mandate | | mandates.cancelled | Mandate cancelled | Mandate-only, payment + mandate | ## What's next? #### [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) A pre-built checkout that's white-labelled, upgradeable, and compliant without additional work. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Guide to creating mandates and handling all mandate actions. #### [Billing Request Events](/docs/collect-payments/events-and-webhooks/billing-request-events) Understand the events fired during a billing request lifecycle. #### [Prefill Customer Details](/docs/optimise/prefill-customer-details) Pre-populate customer data to reduce steps in your custom flow. #### [GoCardless Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) Start with hosted pages to validate your integration — same underlying API. ## Events & Webhooks URL: https://docs.gocardless.com/docs/collect-payments/events-and-webhooks/billing-request-events > Respond to billing request events and webhooks. # Billing Request Events This page covers the events produced as part of a Billing Request's lifecycle, and how you can use them to understand how your customers are behaving across your requests. When things happen in GoCardless's system, we create an [event](/docs/api-reference/events/payment) to record that it happened. You can browse your [events in the dashboard](/docs/developer-resources/viewing-events-in-the-dashboard) or via the API. Integrators who want to respond to events as they happen can follow the [Staying up-to-date with webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) guide, where you configure a webhook endpoint to receive events as they happen. ## Billing Request events Billing Requests are the touchpoint between a merchant and their customer, and everyone can benefit from a high level of visibility into the process. For this reason, we aim to provide events for: Billing Requests are the touchpoint between a merchant and their customer, and everyone can benefit from a high level of visibility into the process. For this reason, we aim to provide events for: - Whenever any state in the Billing Request changes - Payer interactions, such as opening a Billing Request Flow link - Any situations that might require contacting the payer, such as bank authorisation failure Each event aims to reference every resource that might be relevant. Across the events, we have the following link fields: | **Resource** | **Description** | | ------------------------- | -------------------------------------------------------- | | `billing_request` | The billing request ID | | `billing_request_flow` | The flow that triggered the event, if from a flow | | `customer` | Associated customer ID | | `customer_bank_account` | Whatever bank account is associated with the event | | `bank_authorisation` | whatever bank authorisation is associated with the event | | `institution_id` | whatever institution associated with the event | | `payment_request_payment` | payment ID that was created as part of the request | | `mandate_request_mandate` | mandate ID that was created as part of the request | We'll split this section into a header per event, with a small explanation of what the event does. We'll include an example event in the same format you'd see from the [List Events](/docs/api-reference/events/payment) endpoint, or what you'd receive in a webhook. ### billing_request_created Triggered whenever a Billing Request is created. Use this event to register a Billing Request, so that any listening system can respond to subsequent events that follow. The origin can be `api` if created through an integration, or `payer` if created as part of a payer's action, like following a paylink or a Billing Request Template URL. ```json { "id": "EV0039FK74X5Y4", "created_at": "2021-05-03T18:23:08.141Z", "resource_type": "billing_requests", "action": "created", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "payment_request_payment": "PM000SY3392D1T", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "payer", "cause": "billing_request_created", "description": "This billing request has been created." }, "metadata": {} } ``` ### billing_request_flow_created Triggered when a new flow has been created against a Billing Request. This does not mean anyone has visited the flow, just that a flow has been created. ```json { "id": "EV0039FK756APS", "created_at": "2021-05-03T18:23:08.181Z", "resource_type": "billing_requests", "action": "flow_created", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "payment_request_payment": "PM000SY3392D1T", "billing_request_flow": "BRF000011RGT7FDRW90FTGJ1BZ6944DP", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "payer", "cause": "billing_request_flow_created", "description": "A billing request flow has been created against this billing request." }, "metadata": {} } ``` ### billing_request_flow_visited When the Billing Request Flow link is visited, the frontend app will initialise a new session in exchange for the Billing Request Flow ID. This is the first thing that happens upon visiting the flow and will trigger the creation of this event. You can use this event to infer that a payer has visited the flow. ```json { "id": "EV0039FK76YFFR", "created_at": "2021-05-03T18:23:09.435Z", "resource_type": "billing_requests", "action": "flow_visited", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "payment_request_payment": "PM000SY3392D1T", "billing_request_flow": "BRF000011RGT7FDRW90FTGJ1BZ6944DP", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "payer", "cause": "billing_request_flow_visited", "description": "The billing request flow has been visited." }, "metadata": {} } ``` ### billing_request_collect_customer_details Triggered whenever a payer successfully completes the [`collect_customer_details`](/docs/api-reference/billing-request#collect-customer-details) action. Can be used to build funnels to measure how payers progress through the flow. ```json { "id": "EV0039FK77ARRT", "created_at": "2021-05-03T18:23:20.386Z", "resource_type": "billing_requests", "action": "collect_customer_details", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "payment_request_payment": "PM000SY3392D1T", "billing_request_flow": "BRF000011RGT7FDRW90FTGJ1BZ6944DP", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "api", "cause": "billing_request_collect_customer_details", "description": "Customer details have been collected for this billing request." }, "metadata": {} } ``` ### billing_request_collect_bank_account Triggered whenever a payer successfully completes the [`collect_bank_account`](/docs/api-reference/billing-request#collect-bank-account-details) action. Can be used to build funnels to measure how payers progress through the flow. The `customer_bank_account` ID is the bank account that was created as a result of completing this action. ```json { "id": "EV0039FK7845W0", "created_at": "2021-05-03T18:23:32.065Z", "resource_type": "billing_requests", "action": "collect_bank_account", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "payment_request_payment": "PM000SY3392D1T", "billing_request_flow": "BRF000011RGT7FDRW90FTGJ1BZ6944DP", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "api", "cause": "billing_request_collect_bank_account", "description": "Bank account details have been collected for this billing request." }, "metadata": {} } ``` ### billing_request_bank_authorisation_denied Triggered if a payer was redirected to their bank and rejected the authorisation. Payers can always return to the flow and create a new bank authorisation, but the linked authorisation is now permanently denied. ```json { "id": "EV0039FK79TA5M", "created_at": "2021-05-03T18:24:00.063Z", "resource_type": "billing_requests", "action": "bank_authorisation_denied", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "bank_authorisation": "BAU000012N3A4GG", "institution_id": "monzo", "payment_request_payment": "PM000SY3392D1T", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "payer", "cause": "billing_request_bank_authorisation_denied", "bank_account_id": "BA0000QF3HBM4V", "description": "A bank authorisation for this billing request has been denied by the payer." }, "metadata": {} } ``` ### billing_request_bank_authorisation_authorised Triggered if a payer was redirected to their bank and authorised the request. Authorisation of payments can trigger Billing Request fulfilment, depending on the scheme. ```json { "id": "EV0039FK7ATXFE", "created_at": "2021-05-03T18:24:26.509Z", "resource_type": "billing_requests", "action": "bank_authorisation_authorised", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "bank_authorisation": "BAU000012N4B63N", "institution_id": "monzo", "payment_request_payment": "PM000SY3392D1T", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "payer", "cause": "billing_request_bank_authorisation_authorised", "bank_account_id": "BA0000QF3HBM4V", "description": "A bank authorisation for this billing request has been authorised by the payer." }, "metadata": {} } ``` ### billing_request_fulfilled Triggered when the Billing Request has been fulfilled, and the sub-resources have been created. This means any Pay By Banks have been created, along with any DD mandates from the Billing Request. ```json { "id": "EV0039FK7F2AAD", "created_at": "2021-05-03T18:24:26.988Z", "resource_type": "billing_requests", "action": "fulfilled", "links": { "customer": "CU00016Y7P8FPA", "customer_bank_account": "BA0000QF3HBM4V", "payment_request_payment": "PM000SY3392D1T", "billing_request": "BRQ000012HQV2J4" }, "details": { "origin": "gocardless", "cause": "billing_request_fulfilled", "description": "This billing request has been fulfilled, and the resources have been created." }, "metadata": {} } ``` ## What's next? #### [Pay By Bank](/docs/collect-payments/one-off-payments/pay-by-bank) Understand how Pay By Bank payments trigger billing request events. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Events are also fired during mandate setup via Billing Requests. #### [Mandate Events](/docs/collect-payments/events-and-webhooks/mandate-events) Events fired after mandate creation: active, cancelled, failed, expired. #### [Webhooks Overview](/docs/getting-started/stay-up-to-date-with-webhooks) How to configure a webhook endpoint and verify webhook signatures. ## GoCardless Components URL: https://docs.gocardless.com/docs/collect-payments/integration-types/gocardless-components > Embed mandate setup inline in your checkout using the GoCardless Components JavaScript library. # GoCardless Components > **Info: Now live: GoCardless Components** > Embed Direct Debit mandate setup directly inside your checkout. No request needed — follow the > guide below and try it today. GoCardless Components is a JavaScript library for setting up a Direct Debit mandate form directly inside your checkout. Payers fill it in and authorise the mandate without ever leaving your site or app. GoCardless handles compliance, payer name verification, and form validation behind the scenes, while you keep full control over the surrounding experience. Under the hood, Components creates and guides the payer through a **Billing Request** — the GoCardless object that brings together the customer, their authorisation, and their bank details into a single, manageable object (see the [Billing Requests overview](/docs/collect-payments#collect-payments) for more). Unlike the [Drop-in Flow](/docs/collect-payments/integration-types/javascript-drop-in-flow), which renders as a modal, Components embeds inline in your checkout and offers deeper styling control — with less build effort than fully [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). Today, Components supports **Bacs (UK) mandate creation only**, but are soon expanding to other schemes like SEPA. **Best for:** - Customers setting up their Direct Debit without leaving your website or app - Fine-tuning your checkout's design (colours, fonts, spacing, brand) without building from scratch - Easy maintenance and updates, without rebuilding your integration each time - Teams who want more UX control than Hosted Pages, with less build effort than a fully custom API integration **Out of the box:** - Embedded UI mounted into any element on your page - Built-in form validation, error states, and retry behaviour - Prefill customer details from your existing flow - Compliant mandate authorisation flow If you need to collect a payment alongside the mandate, or need a scheme we don't yet cover, use [Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages), [Drop-in Flow](/docs/collect-payments/integration-types/javascript-drop-in-flow), or [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages) instead. ![Entire Flow](/images/docs/collect-payments/integration-types/gocardless-components/image-4.gif) ## 1. Setup You can skip to [Implementation](#2-implementation) if you already have: - An access token with `GoCardless Components` enabled - A server with an endpoint capable of minting session tokens from that access token - A server endpoint capable of fulfilling billing requests via the GoCardless API ### 1.1. Getting an access token The library authenticates via a short-lived session token, minted server-side from a long-lived access token. #### For merchants Go to the [/developers/access-tokens](https://manage.gocardless.com/developers/access-tokens?action=create) in the GoCardless dashboard: 1. Enter a name to identify this token 2. Select `Read-write access` scope 3. Turn **"Enable GoCardless Components"** ON for that token 4. Provide the domain where you will use the component 5. Click **Create access token** > **Info:** > For security, the access token is validated against the domain provided at creation. During local > development, requests from `localhost` are exempt from domain validation. > **Info:** > This doesn't need to be a dedicated token used only for Components. Enabling GoCardless Components > on an access token only adds the capability required to mint `ui_components` session tokens from > it — it doesn't restrict, or get restricted by, anything else that same read-write token is used > for elsewhere in your integration. #### For partner integrators Refer to the [Partners](/docs/collect-payments/integration-types/gocardless-components/partners) page for detailed examples on how to mint a session token per merchant. ### 1.2. Setting up an endpoint to mint session tokens The library should never see your access token directly. Instead, your backend uses it to mint a short-lived session token, which is what gets passed to the library components. To do this, make the following request to GoCardless using the access token: ```json POST /session_tokens Authorization: Bearer YOUR_ACCESS_TOKEN { "session_tokens": { "policies": [ "ui_components" ] } } ``` This returns a response of the form: ```json { "session_tokens": { "id": "...", "token": "..." } } ``` `session_tokens.token` is the value your `sessionToken` callback (see [Configuring the Library](#22-configure-the-library)) should resolve to. #### Token rules - Mint one session token per checkout, don't share it across customers or checkout sessions. - Don't cache it, always mint a fresh one from your `sessionToken` callback. This is also why `sessionToken` is a `() => Promise` callback rather than a static token string in the library's config — it's not possible to pass a fixed token, by design. - Tokens expire after 30 minutes absolute, or after 10 minutes idle. The idle timeout can't be observed or inferred. If a request to the GoCardless API fails because the token has expired, the library automatically calls your `sessionToken` callback again and retries once, so your endpoint should be able to be called repeatedly throughout longer flows. A second consecutive failure is treated as unrecoverable and won't be retried again. > **Info: Why isn** > Session tokens are handed to untrusted, browser-side code, so the `/session_tokens` response is > kept deliberately minimal — it doesn't expose an expiry timestamp. Don't try to infer or track > expiry client-side; rely on the retry-once behaviour above instead. > **Warning: Securing your session-token minting endpoint** > Your `sessionToken` callback runs in the browser and calls out to this endpoint, so treat it as > public-facing even though it lives on your server. Require your own application's authentication > (e.g. the payer's logged-in session) before minting a token, and rate-limit it — each call mints a > new session token against your access token. The resulting token is already scoped server-side to > the `ui_components` policy, so it can't reach the rest of the GoCardless API, but the endpoint > itself shouldn't blindly trust parameters it receives from the browser either. ### 1.3. Setting up a fulfilment endpoint When a payer completes the Components checkout flow, a callback signals that the billing request is ready to fulfil. You are responsible for calling `POST /billing_requests//actions/fulfil` from your server at that point. See the [API reference](/docs/api-reference/billing-request#fulfil-a-billing-request) for full details. Example fulfilment endpoint in Ruby: ```ruby require 'sinatra' require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: '', environment: :sandbox ) def validate_session_token(session_token, billing_request_id) session_token_client = GoCardlessPro::Client.new( access_token: session_token, environment: :sandbox ) session_token_client.billing_requests.get(billing_request_id) end def fulfil_billing_request(billing_request_id) client.billing_requests.fulfil(billing_request_id) end post '/fulfil-billing-request/:billing_request_id' do billing_request_id = params[:billing_request_id] session_token = request.env['HTTP_SESSION_TOKEN'] begin validate_session_token(session_token, billing_request_id) fulfil_billing_request(billing_request_id) rescue GoCardlessPro::Error => e status e.code content_type :json { success: false, error: e.message }.to_json end end ``` ## 2. Implementation ### 2.1. Add the library to your project Add the GoCardless Components library: ```html ``` Loading this script attaches `GcComponents` to the global window object — this is what you'll use in the next step to configure the library. > **Info:** > `/latest` always reflects the most recent published version of the library. A specific release can > be accessed by using `/` (e.g. `/2.3.0`) instead. ### 2.2. Configure the Library Initialise the library with `GcComponents.init(...)`, passing the configuration: ```javascript const gc = GcComponents.init({ environment: "sandbox", sessionToken: () => fetch("/your-backend/session-token").then((r) => r.text()), onEvent: (event) => logEvent(event), onError: (error) => logError(error), }); ``` | Property | Description | Required | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | | `environment` | The environment in which you want to use Components (`local`, `live`, `sandbox`, `live-staging` or `sandbox-staging`). | Yes | | `sessionToken` | A callback returning a fresh session token (see [Setting up an endpoint to mint session tokens](#12-setting-up-an-endpoint-to-mint-session-tokens)) | Yes | | `appearance` | Custom appearance configuration, applied to every component (see [Customisation](#4-customisation)) | No | | `enableAnalytics` | Whether to enable analytics tracking. Defaults to `true`. | No | | `onEvent` | Callback invoked for every public event emitted by a mounted component (see [Handling errors and events](#5-handling-errors-and-events)) | No | | `onError` | Fallback error callback for any mounted component that doesn't define its own `onError` | No | | `locale` | The target language and region for regionalization, with supported values including `en-GB`, `en-US`, `fr-FR`, `de-DE` `es-ES` `it-IT` `nl-NL` and `pt-PT`. Default: `en-GB` | No | ### 2.3. Create a Billing Request Component #### Select a mount target Create a `` where you want the component to appear: ```html
``` #### Initialise component ```javascript const gc = GcComponents.init({ environment: "sandbox", sessionToken: () => fetch("/your-backend/session-token").then((r) => r.text()), onEvent: (event) => logEvent(event), onError: (error) => logError(error), }); const brComponent = gc.createComponent("billing-request", { schemes: [GcComponents.Scheme.Bacs], onReadyToFulfil: (billingRequestId) => fulfil(billingRequestId), onError: (error) => console.error("Error: ", error), }); brComponent.mount("#gc-billing"); ``` | Property | Description | Required | | ----------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------- | | schemes | The payment schemes to enable, as an array (e.g. `[Scheme.Bacs]`); currently only `bacs` and `sepa` are supported | No | | creditorId | ID of the creditor to create the billing request under | No | | prefilledCustomer | Prefills the customer/billing details form (see below) | No | | appearance | Custom appearance configuration, merged on top of the top-level `appearance` | No | | onReadyToFulfil | `(billingRequestId: string) => void` — called once the customer has submitted everything needed to fulfil the billing request | Yes | | onError | `(error: GoCardlessError) => void` — called on error, in addition to the event bus | No | > **Warning:** > You must implement `onReadyToFulfil`. The Billing Component waits up to **10 seconds** for the > billing request to be fulfilled before timing out and cancelling it. > **Info:** > Configured schemes must be valid for the merchant. If multiple schemes are configured or none are > provided, the billing request component automatically displays a currency selector so the payer > can choose their preferred currency for setting up the mandate ![Billing Component Form](/images/docs/collect-payments/integration-types/gocardless-components/image.png) ## 3. Testing Run through the checkout flow end to end and confirm you reach the confirmation screen without errors. Then verify the mandate was created via the GoCardless dashboard or API. ![Successful DD](/images/docs/collect-payments/integration-types/gocardless-components/image-2.png) ## 4. Customisation Pass an `appearance` object in your config to match Components to your brand: Components can be customised to fit the UI of your page. This is done through the appearance object, either globally in `GcComponents.init(...)`, or per-component, where it's merged on top of the global one. ```javascript const appearance = { backgroundColor: "#bfe6f2", inputBorderRadius: "0px", wrapperBorderRadius: "0", }; const gc = GcComponents.init({ environment: "sandbox", sessionToken: fetchSessionToken, appearance, }); gc.createComponent("billing-request", { appearance: { buttonColor: "#004d40", }, }).mount("#gc-billing"); ``` You can modify colours, fonts, borders, padding etc. and set customisation on particular element types. All unset variables fall back to GoCardless defaults. Full default theme: ```json { backgroundColor: "#F9F9F9", bodyFontSize: "14px", bodyFontWeight: FontWeight.normal, buttonBorderRadius: "32px", buttonPadding: "8px 20px", buttonPrimaryColor: "#1f2937", buttonPrimaryHoverBackgroundColor: "#4b5563", buttonPrimaryHoverTextColor: "#f9fafb", buttonPrimaryTextColor: "#f9fafb", buttonSubmitTextContent: "Set up direct debit", captionFontSize: "12px", captionFontWeight: FontWeight.normal, checkboxBackgroundColor: "#1f2937", checkboxSize: "16px", checkboxTextColor: "#1f2937", dropdownFooterBackgroundColor: "#faf9f7", dropdownFooterBorderColor: "#dfddda", dropdownHoverBackgroundColor: "#1f2937", dropdownHoverTextColor: "#FFFFFF", dropdownPadding: "8px", formValidationErrorColor: "#C52F2F", formVerticalSpacing: "12px", headerFontWeight: FontWeight.medium, inputBackgroundColor: "#FFFFFF", borderColor: "#9ca3af", inputBorderRadius: "4px", inputPadding: "12px 16px", inputPlaceholderColor: "#6b7280", inputTextColor: "#1f2937", labelTextColor: "#4b5563", linkHoverTextColor: "#3a66b9", linkTextColor: "#0464ff", loadingSpinnerColor: "#1f2937", separatorColor: "#9ca3af", textColor: "#000000", textFontFamily: 'Inter, "Helvetica Neue", Helvetica, Arial, sans-serif', tagBackgroundColor: "#e5e7eb", tagBorderRadius: "4px", tagPadding: "0 4px", tagTextColor: "#1f2937", wrapperBorderColor: "#9ca3af", wrapperBorderRadius: "8px", wrapperBorderWidth: "1px", wrapperMargin: "16px", } ``` ## 5. Handling errors and events Each component's public events are forwarded to the single top-level onEvent callback. Errors are reported via onError, either on the component config or as a top-level fallback in `GcComponents.init(...)`. #### 5.1 Troubleshooting errors Errors are reported as a `GoCardlessError` object of the following shape: ``` { code: 401, message: "Authentication failed. Please check your configuration.", isUnrecoverable: true, type: "authentication" } ``` - `code` — an HTTP-style status code - `message` — a human-readable description - `isUnrecoverable` — whether the checkout flow can continue after this error, or must be restarted - `type` / `requestId` / `errors` — optional, populated for errors returned by the GoCardless API #### 5.2 Common errors - Billing request creation failed — the creation of a new billing request failed. Your session token may have expired or be invalid. - Scheme not supported — you have attempted to use a scheme that Components does not currently support. Ensure `schemes` only contains values from the enum `Scheme`. - HTML element not found — the library was unable to find the element in which to embed the component using your provided `target` selector. Ensure your selector is valid and present in the DOM before calling `init(...)`. #### 5.3 Session token expiry If a request to the GoCardless API fails because the session token has expired, the library automatically calls your `sessionToken` callback again to mint a fresh token and retries the request once. If the retry also fails, the error is marked as unrecoverable and the component will prompt the customer to restart the flow. #### 5.4 Checkout errors When an error occurs during the flow, GoCardless renders an error screen and calls your `onError` callback with a `GoCardlessError` object: ```json { "type": "authentication", "message": "Authentication failed. Please check your configuration", "metadata": { "subType": "invalid_api_usage", "requestId": "1f6f8649-6e40-4b50-936b-a8924dc7d2cb", "statusCode": "401" }, "isUnrecoverableError": false } ``` | Field | Description | | ---------------------- | ------------------------------------------------------------------------------ | | `type` | Error type | | `message` | Detailed error message | | `metadata` | `subType`, `requestId`, `statusCode` | | `isUnrecoverableError` | `true` if GoCardless could not offer a retry — provide the payer a way to exit | | Error | Description | | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `TimeoutError` | `onReadyToFulfil` was triggered but the request was not fulfilled within 10 seconds. GoCardless cancels the request and offers a retry | | `Authentication` (with `SessionTokenExpired`) | Session tokens are valid for 30 minutes. If the token expires mid-flow, the payer must restart | ## 6. Prefilled customer details Pass `prefilledCustomer` in your `BillingRequest` factory to pre-populate the billing form. Bank details cannot be prefilled for security reasons. ```javascript const gc = GcComponents.init({ environment: "sandbox", sessionToken: fetchSessionToken, }); const brComponent = gc.createComponent("billing-request", { prefilledCustomer: { firstName: "Components", lastName: "Tester", email: "components-tester@example.com", addressLine1: "65 Goswell Road", addressLine2: "", city: "London", postalCode: "EC1V 7EN", }, }); brComponent.mount("#gc-billing"); ``` ![Prefilled form](/images/docs/collect-payments/integration-types/gocardless-components/image-3.png) ## 7. Analytics and data tracking GoCardless Components collects usage data to improve performance and usability. Data collection is enabled by default and can be disabled: ```javascript const config = { environment: "sandbox", sessionToken: fetchSessionToken, enableAnalytics: false, }; GcComponents.init(config); ``` | Purpose | Service | Cookies | Description | | --------- | -------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | | Analytics | GoCardless / Segment | `ajs_anonymous_id`, `analytics_session_id`, `analytics_session_id.last_access` | Tracks user events (clicks, form interactions) to improve UX. Processed via Segment | As an integrator, you are responsible for obtaining user consent for data collection, disclosing GoCardless and Segment as third parties, and updating your cookie policy accordingly. ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Learn how to collect bank account details and create mandates via the API. #### [Integration Types Overview](/docs/collect-payments) Compare all integration options to find the right fit for your use case. #### [GoCardless Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) The fastest integration — redirect to a GoCardless-hosted checkout. #### [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages) Full API control for teams that want complete UX ownership. ## GoCardless Hosted Pages Overview URL: https://docs.gocardless.com/docs/collect-payments/integration-types/gocardless-hosted-pages > Overview of the GoCardless Hosted Pages integration. # GoCardless Hosted Pages This is the fastest way to start collecting payments. Redirect your customers to a GoCardless-hosted page to complete mandate setup and payment authorisation. Once done, they're redirected back to your site. Supports: **All payment types** (one-off, recurring, instalments, Pay By Bank, Instant + DD, Commercial VRP) ## Best for - Quick implementation with minimal development - Teams without front-end development resources - Prototyping and early releases - A proven, scalable, compliant payment journey ## What you get out of the box - Mobile-responsive design - Multi-language support - Scheme-appropriate authorisation flows per country - Regulatory compliance handled - Optimised conversion flow You can set your company name and logo. For more control over the look and feel, consider the [Drop-in Flow](/docs/collect-payments/integration-types/javascript-drop-in-flow) or [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages) approach. ## How it works 1. Create a Billing Request via the API, specifying the payment type 2. Create a Billing Request Flow; this generates a hosted URL 3. Redirect your customer to the URL 4. Customer completes authorisation on the GoCardless-hosted page 5. Customer is redirected back to your redirect_uri 6. Listen for webhooks to confirm the outcome ## Step-by-step guide ### Create a billing request The Billing Request defines what you're collecting. The payload differs by payment type: #### Direct Debit Mandate ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'mandate_request': { 'scheme': 'bacs', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { mandate_request: { scheme: 'bacs' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000301", "status": "pending", "mandate_request": { "scheme": "bacs", "currency": "GBP" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "collect_bank_account", "required": true, "completed": false }, { "type": "confirm_payer_details", "required": true, "completed": false } ] } } ``` #### Pay By Bank ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "payment_request": { "description": "Order #9012", "amount": 12000, "currency": "GBP", "scheme": "faster_payments" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'payment_request' => [ 'description' => 'Order #9012', 'amount' => 12000, 'currency' => 'GBP', 'scheme' => 'faster_payments', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'payment_request': { 'description': 'Order #9012', 'amount': 12000, 'currency': 'GBP', 'scheme': 'faster_payments', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { payment_request: { description: 'Order #9012', amount: 12000, currency: 'GBP', scheme: 'faster_payments' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withPaymentRequestDescription("Order #9012") .withPaymentRequestAmount(12000) .withPaymentRequestCurrency("GBP") .withPaymentRequestScheme("faster_payments") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ payment_request: { description: "Order #9012", amount: 12000, currency: "GBP", scheme: "faster_payments", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { PaymentRequest = new BillingRequestCreateRequest.BillingRequestPaymentRequest { Description = "Order #9012", Amount = 12000, Currency = "GBP", Scheme = "faster_payments" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ PaymentRequest: &gocardless.BillingRequestCreateParamsPaymentRequest{ Description: "Order #9012", Amount: 12000, Currency: "GBP", Scheme: "faster_payments", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000302", "status": "pending", "payment_request": { "amount": 12000, "currency": "GBP", "scheme": "faster_payments" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "select_institution", "required": true, "completed": false }, { "type": "bank_authorisation", "required": true, "completed": false } ] } } ``` #### Direct Debit + Pay By Bank ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "payment_request": { "description": "First payment", "amount": 5000, "currency": "GBP", "scheme": "faster_payments" }, "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'payment_request' => [ 'description' => 'First payment', 'amount' => 5000, 'currency' => 'GBP', 'scheme' => 'faster_payments', ], 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'payment_request': { 'description': 'First payment', 'amount': 5000, 'currency': 'GBP', 'scheme': 'faster_payments', }, 'mandate_request': { 'scheme': 'bacs', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { payment_request: { description: 'First payment', amount: 5000, currency: 'GBP', scheme: 'faster_payments' }, mandate_request: { scheme: 'bacs' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withPaymentRequestDescription("First payment") .withPaymentRequestAmount(5000) .withPaymentRequestCurrency("GBP") .withPaymentRequestScheme("faster_payments") .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ payment_request: { description: "First payment", amount: 5000, currency: "GBP", scheme: "faster_payments", }, mandate_request: { scheme: "bacs", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { PaymentRequest = new BillingRequestCreateRequest.BillingRequestPaymentRequest { Description = "First payment", Amount = 5000, Currency = "GBP", Scheme = "faster_payments" }, MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ PaymentRequest: &gocardless.BillingRequestCreateParamsPaymentRequest{ Description: "First payment", Amount: 5000, Currency: "GBP", Scheme: "faster_payments", }, MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000303", "status": "pending", "payment_request": { "amount": 5000, "currency": "GBP", "scheme": "faster_payments" }, "mandate_request": { "scheme": "bacs", "currency": "GBP" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "collect_bank_account", "required": true, "completed": false }, { "type": "confirm_payer_details", "required": true, "completed": false }, { "type": "select_institution", "required": true, "completed": false }, { "type": "bank_authorisation", "required": true, "completed": false } ] } } ``` #### Variable Recurring Payments (VRP) ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "fallback_enabled": true, "purpose_code": "loan", "payment_context_code": "billing_goods_and_services_in_arrears", "payment_purpose_code": "bank_loan_delayed_draw_funding", "mandate_request": { "scheme": "faster_payments", "constraints": { "start_date": "2024-11-01", "max_amount_per_payment": 50000, "periodic_limits": [{ "period": "month", "max_total_amount": 100000, "alignment": "creation_date" }] } } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'fallback_enabled' => true, 'purpose_code' => 'loan', 'payment_context_code' => 'billing_goods_and_services_in_arrears', 'payment_purpose_code' => 'bank_loan_delayed_draw_funding', 'mandate_request' => [ 'scheme' => 'faster_payments', 'constraints' => [ 'start_date' => '2024-11-01', 'max_amount_per_payment' => 50000, 'periodic_limits' => [ [ 'period' => 'month', 'max_total_amount' => 100000, 'alignment' => 'creation_date', ], ], ], ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'fallback_enabled': True, 'purpose_code': 'loan', 'payment_context_code': 'billing_goods_and_services_in_arrears', 'payment_purpose_code': 'bank_loan_delayed_draw_funding', 'mandate_request': { 'scheme': 'faster_payments', 'constraints': { 'start_date': '2024-11-01', 'max_amount_per_payment': 50000, 'periodic_limits': [ { 'period': 'month', 'max_total_amount': 100000, 'alignment': 'creation_date', }, ], }, }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { fallback_enabled: true, purpose_code: 'loan', payment_context_code: 'billing_goods_and_services_in_arrears', payment_purpose_code: 'bank_loan_delayed_draw_funding', mandate_request: { scheme: 'faster_payments', constraints: { start_date: '2024-11-01', max_amount_per_payment: 50000, periodic_limits: [ { period: 'month', max_total_amount: 100000, alignment: 'creation_date' } ] } } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withFallbackEnabled(true) .withPurposeCode("loan") .withPaymentContextCode("billing_goods_and_services_in_arrears") .withPaymentPurposeCode("bank_loan_delayed_draw_funding") .withMandateRequestScheme("faster_payments") .withMandateRequestConstraintsStartDate("2024-11-01") .withMandateRequestConstraintsMaxAmountPerPayment(50000) .withMandateRequestConstraintsPeriodicLimitsBuilder() .withPeriod("month") .withMaxTotalAmount(100000) .withAlignment("creation_date") .done() .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ fallback_enabled: true, purpose_code: "loan", payment_context_code: "billing_goods_and_services_in_arrears", payment_purpose_code: "bank_loan_delayed_draw_funding", mandate_request: { scheme: "faster_payments", constraints: { start_date: "2024-11-01", max_amount_per_payment: 50000, periodic_limits: [ { period: "month", max_total_amount: 100000, alignment: "creation_date", }, ], }, }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { FallbackEnabled = true, PurposeCode = "loan", PaymentContextCode = "billing_goods_and_services_in_arrears", PaymentPurposeCode = "bank_loan_delayed_draw_funding", MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "faster_payments", Constraints = new BillingRequestCreateRequest.BillingRequestMandateRequestConstraints { StartDate = "2024-11-01", MaxAmountPerPayment = 50000, PeriodicLimits = new List { new BillingRequestCreateRequest.BillingRequestMandateRequestConstraintsPeriodicLimit { Period = "month", MaxTotalAmount = 100000, Alignment = "creation_date" } } } } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } fallbackEnabled := true params := gocardless.BillingRequestCreateParams{ FallbackEnabled: &fallbackEnabled, PurposeCode: "loan", PaymentContextCode: "billing_goods_and_services_in_arrears", PaymentPurposeCode: "bank_loan_delayed_draw_funding", MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "faster_payments", Constraints: &gocardless.BillingRequestCreateParamsMandateRequestConstraints{ StartDate: "2024-11-01", MaxAmountPerPayment: 50000, PeriodicLimits: []gocardless.BillingRequestCreateParamsMandateRequestConstraintsPeriodicLimit{ { Period: "month", MaxTotalAmount: 100000, Alignment: "creation_date", }, }, }, }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000301", "created_at": "2024-11-01T00:00:00.000Z", "status": "pending", "mandate_request": { "scheme": "faster_payments", "currency": "GBP", "verify": "recommended", "consent_type": "recurring", "description": null, "sweeping": false, "payer_requested_dual_signature": false, "metadata": {}, "links": {}, "constraints": { "start_date": "2024-11-01", "end_date": null, "max_amount_per_payment": 50000, "periodic_limits": [ { "period": "month", "max_total_amount": 100000, "alignment": "creation_date", "max_amount_per_period": null, "max_payments": null } ] } }, "payment_request": null, "subscription_request": null, "instalment_schedule_request": null, "metadata": {}, "fallback_enabled": true, "fallback_occurred": false, "purpose_code": "loan", "payment_purpose_code": "bank_loan_delayed_draw_funding", "sign_flow_url": null, "auto_fulfil": false, "actions": [ { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "collect_customer_details": { "default_country_code": "GB", "incomplete_fields": { "customer": ["given_name", "family_name", "email"], "customer_billing_detail": ["address_line1", "city", "postal_code", "country_code"] } } }, { "type": "select_institution", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "institution_guess_status": "pending" }, { "type": "collect_bank_account", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "available_country_codes": ["GB"] }, { "type": "bank_authorisation", "required": true, "completes_actions": [], "requires_actions": ["select_institution", "collect_customer_details"], "status": "pending", "bank_authorisation": { "authorisation_type": "mandate" } }, { "type": "confirm_payer_details", "required": true, "completes_actions": [], "requires_actions": ["collect_customer_details", "collect_bank_account"], "status": "pending" } ], "links": { "mandate_request": "MRQ0000301" } } } ``` ### Create a billing request flow This generates the hosted URL where the customer completes authorisation. ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequestFlows()->create([ "params" => [ "redirect_uri" => "https://my-company.com/landing", "exit_uri" => "https://my-company.com/exit", "links" => [ "billing_request" => "BRQ000010NMDMH2" ] ] ]); ```` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_request_flows.create(params={ "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } }) ```` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_request_flows.create( params: { redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create() .withRedirectUri("https://my-company.com/landing") .withExitUri("https://my-company.com/exit") .withLinksBillingRequest("BRQ000010NMDMH2") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequestFlow = await client.billingRequestFlows.create({ redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequestFlows.CreateAsync( new GoCardless.Services.BillingRequestFlowCreateRequest() { RedirectUri = "https://my-company.com/landing", ExitUri = "https://my-company.com/exit", Links = new GoCardless.Services.BillingRequestFlowCreateRequest.BillingRequestFlowLinks { BillingRequest = "BRQ000010NMDMH2", }, } ); GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow; ``` ```http POST https://api.gocardless.com/billing_request_flows HTTP/1.1 { "billing_request_flows": { "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here"; opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(accessToken, opts) billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams{} billingRequestFlowCreateParams.RedirectUri = "https://my-company.com/landing" billingRequestFlowCreateParams.ExitUri = "https://my-company.com/exit" billingRequestFlowCreateParams.Links.BillingRequest = "BRQ000010NMDMH2" billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams) ``` ```cli gc create billing_request_flow \ -d "links[billing_request]= BRQ000010NMDMH2" \ -d 'redirect_uri=https://my-company.com/landing' \ -d 'exit_uri=https://my-company.com/exit' ``` Response: ```json { "billing_request_flows": { "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=", "lock_customer_details": false, "lock_bank_account": false, "auto_fulfil": true, "created_at": "2021-03-30T16:23:10.679Z", "expires_at": "2021-04-06T16:23:10.679Z", "redirect_uri": "https://my-company.com/completed", "links": { "billing_request": "BRQ123" } } } ``` The response includes an authorisation_url; redirect your customer there. ### Handle the redirect Send your customer to the authorisation_url. GoCardless collects any required details: name, email, bank account and handles the scheme-appropriate authorisation flow. When the customer completes or exits, they are redirected to your redirect_uri or exit_uri with query parameters: | Parameter | Example value | | ----------------------- | ------------- | | billing_request_id | BRQ0000101 | | billing_request_flow_id | BRF0000101 | > **Warning:** > Don't use the redirect to confirm the outcome. Always use webhooks. ### Listen for webhooks | Event | Meaning | | ---------------------------- | ---------------------------------------- | | billing_request_fulfilled | Customer completed the flow | | mandate_created | Mandate is active (for DD payment types) | | payment_confirmed | Payment confirmed (for Pay By Bank) | | billing_request_flow_expired | The customer didn't complete on time | #### Pre-collecting customer details If you already have the customer's name, email, and address, submit them before creating the flow. The hosted page skips those fields or locks them if you prefer. ### Collect customer details (optional) ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->collectCustomerDetails("BR123", [ "params" => [ "customer" => [ "email" => "paddington@bearthings.com" "given_name" => "Paddington", "family_name" => "Bear" ], "customer_billing_detail" => [ "address_line1" => "32 Windsor Gardens", "city" => "London", "postal_code" => "W9 3RG", "country_code" => "GB" ] ] ]); ```` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.collect_customer_details("BR123", params={ customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB", } }) ```` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_customer_details("BR123", { params: { customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB". } } }) ``` ```java @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_customer_details("BR123", { params: { customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB" } } }) ``` ```javascript const constants = require('gocardless-nodejs/constants'); const gocardless = require('gocardless-nodejs'); const client = gocardless('your_access_token_here', constants.Environments.Sandbox); const resp = await client.billingRequests.collectCustomerDetails("BR123", { customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB" } }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var customer = new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomer { Email = "paddington@bearthings.com", GivenName = "Paddington", FamilyName = "Bear", }; var customerBillingDetail =new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomerBillingDetail { AddressLine1 = "32 Windsor Gardens", City = "London", PostalCode = "W9 3RG", CountryCode = "GB", }; var resp = await gocardless.BillingRequests.CollectCustomerDetails("BR123", new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest { Customer = customer, CustomerBillingDetail = customerBillingDetail, }); ``` ```http POST /billing_requests/BRQ000010NMDMH2/actions/collect_customer_details HTTP/1.1 { "data": { "customer": { "email": "paddington@bearthings.com", "given_name": "Paddington", "family_name": "Bear" }, "customer_billing_detail": { "address_line1": "32 Windsor Gardens", "city": "London", "postal_code": "W9 3RG", "country_code": "GB" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCollectCustomerDetailsParams := gocardless.BillingRequestCollectCustomerDetailsParams{ Customer: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomer{ GivenName: "Paddington", FamilyName: "Bear", Email: "paddington@bearthings.com", }, CustomerBillingDetail: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomerBillingDetail{ AddressLine1: "32 Windsor Gardens", City: "London", PostalCode: "W9 3RG", CountryCode: "GB", }, } billingRequest, err := client.BillingRequests.CollectCustomerDetails(context, "BR123", billingRequestCollectCustomerDetailsParams) ``` **Response:** Updated Billing Request with collect_customer_details marked completed. ### Collect bank account (optional) ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->collectBankAccount("BRQ000010NMDMH2", [ "params" => [ "account_number" => "55779911", "branch_code" => "200000", "account_holder_name" => "Frank Osborne", "country_code" => "GB" ] ]); ```` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.collect_bank_account("BRQ000010NMDMH2", params={ account_number: "55779911", branch_code: "200000", account_holder_name: "Frank Osborne", country_code: "GB", }) ```` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_bank_account("BRQ000010NMDMH2", { params: { account_number: "55779911", branch_code: "200000", account_holder_name: "Frank Osborne", country_code: "GB", } }) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); client.billingRequests().collectBankAccount("BRQ000010NMDMH2") .withAccountNumber("55779911") .withBranchCode("200000") .withAccountHolderName("Frank Osborne") .withCountryCode("GB") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const resp = await client.billingRequests.collectBankAccount("BRQ000010NMDMH2", { account_number: "55779911", branch_code: "200000", account_holder_name: "Frank Osborne", country_code: "GB", }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequests.CollectBankAccountAsync("BRQ000010NMDMH2", new BillingRequestCollectBankAccountRequest { AccountNumber = "55779911", BranchCode = "200000", AccountHolderName = "Frank Osborne", CountryCode = "GB", }); ``` ```http POST /billing_requests/BRQ000010NMDMH2/actions/collect_bank_account HTTP/1.1 { "data": { "account_number": "11223344", "branch_code": "040004", "account_holder_name": "Paddington Bear", "country_code": "GB" } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCollectBankAccountParams := gocardless.BillingRequestCollectBankAccountParams{ BranchCode: "200000", CountryCode: "GB", AccountNumber: "55779911", AccountHolderName: "Frank Osborne", } billingRequest, err := client.BillingRequests.CollectBankAccount(context, "BRQ000010NMDMH2", billingRequestCollectBankAccountParams) ``` **Response:** Updated Billing Request with collect_bank_account marked completed. > **Info:** > When creating the Billing Request Flow, pass `lock_customer_details: true` and/or > `lock_bank_account: true` to prevent customers editing pre-filled values. ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates and collect bank account details via the API. #### [Prefill Customer Details](/docs/optimise/prefill-customer-details) Skip form steps by supplying customer details before the hosted flow. #### [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) A pre-built checkout that's white-labelled, upgradeable, and compliant without additional work. #### [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages) Full API control for teams that need complete UX ownership. ## Importing Mandates URL: https://docs.gocardless.com/docs/collect-payments/setting-up-mandates/importing-mandates > Import existing mandates into GoCardless. # Importing Mandates ## Why import mandates? Importing mandates allows you to migrate existing Direct Debit authorisations from another provider into GoCardless without requiring your customers to re-authorise. Once imported, you can manage and collect against them alongside any mandates created directly through GoCardless. > **Info:** > This feature must be enabled on your account before use. Contact > [support@gocardless.com](mailto:support@gocardless.com) or your account manager to request access. > **Info:** > Each mandate import can only contain mandates from a single scheme. If you're migrating mandates > across multiple schemes, you'll need a separate import for each. ## How it works 1. You create a Mandate Import specifying the scheme 2. You add an entry for each mandate you want to import 3. You submit the import for review 4. GoCardless reviews and approves the import 5. Mandates are created, and you reconcile them with your internal records > **Info: What happens to your customers** > Customers do not need to take any action. Their mandate reference may change — if your scheme > requires this, you'll need to notify customers of the new reference in line with your scheme > rules. ## Step-by-step guide ### Create a Mandate Import ```http POST https://api.gocardless.com/mandate_imports HTTP/1.1 { "mandate_imports": { "scheme": "sepa_core" } } HTTP/1.1 201 (Created) Location: /mandate_imports/IM000010790WX1 { "mandate_imports": { "id": "IM000010790WX1", "scheme": "sepa_core", "status": "created", "created_at": "2018-03-12T14:03:04.000Z" } } ``` ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $mandateImport = $client->mandateImports()->create([ "params" => ["scheme" => "sepa_core"] ]); ``` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') mandate_import = client.mandate_imports.create(params={ "scheme": "sepa_core" }); ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) mandate_import = @client.mandate_imports.create(params: { scheme: "sepa_core" }) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); MandateImport mandateImport = client.mandateImports().create() .withScheme(SEPA_CORE) .execute(); ``` ```javascript const accessToken = "your_access_token"; const constants = require("gocardless-nodejs/constants"); const client = require("gocardless-nodejs")(accessToken, constants.Environments.Sandbox); const mandateImport = await client.mandateImports.create({ scheme: "sepa_core", }); ``` ```net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var importRequest = new GoCardless.Services.MandateImportCreateRequest() { Scheme = MandateImportCreateRequest.MandateImportScheme.SepaCore }; var importResponse = await gocardless.MandateImports.CreateAsync(importRequest); GoCardless.Resources.MandateImport mandateImport = importResponse.MandateImport; ``` ```go ctx := context.TODO() mandateImportCreateParams := goCardless.MandateImportCreateParams{ Scheme: "sepa_core", } client.MandateImports().Create(ctx, mandateImportCreateParams) ``` Hold onto the ID, you'll need it to add entries and submit. ### Add Mandate Import Entries Add one entry per mandate. Each entry requires: - `links.mandate_import:` the ID from Step 1 - `customer:` identifying details for the customer - `bank_account:` account holder name and either an IBAN or [local bank details] - `record_identifier:` Your own reference for this mandate (see below) > **Warning: Set record_identifier for every entry** > This is your reference string that links each entry back to your internal records. Without it, > reconciling your existing customer IDs with the new GoCardless IDs after the import is processed > is significantly harder. It must be unique within the mandate import. SEPA mandates only: You must also provide amendment details, the original mandate reference, creditor ID, and creditor name from your previous provider. These are required by the SEPA scheme to maintain a valid audit trail. ```php $mandateImportEntry = $client->mandateImportEntries()->create([ "params" => [ "links" => [ "mandate_import" => $mandateImport->id ], "record_identifier" => "bank-file.xml/line-1", "customer" => [ "company_name" => "Théâtre du Palais-Royal", "email" => "moliere@tdpr.fr" ], "bank_account" => [ "account_holder_name" => "Jean-Baptiste Poquelin", "iban" => "FR14BARC20000055779911" ], // Amendment details are required for SEPA only "amendment" => [ "original_mandate_reference" => "REFNMANDATE", "original_creditor_id" => "FR123OTHERBANK", "original_creditor_name" => "Amphitryon" ] ] ]); ``` ```python mandate_import_entry = client.mandate_import_entries.create(params={ "links": { "mandate_import": mandate_import.id }, "record_identifier": "bank-file.xml/line-1", "customer": { "company_name": "Théâtre du Palais-Royal", "email": "moliere@tdpr.fr" }, "bank_account": { "account_holder_name": "Jean-Baptiste Poquelin", "iban": "FR14BARC20000055779911" }, # Amendment details are required for SEPA only "amendment": { "original_mandate_reference": "REFNMANDATE", "original_creditor_id": "FR123OTHERBANK", "original_creditor_name": "Amphitryon" } }) ``` ```ruby mandate_import_entry = @client.mandate_import_entries.create(params: { links: { mandate_import: mandate_import.id }, record_identifier: "bank-file.xml/line-1", customer: { company_name: "Théâtre du Palais-Royal", email: "moliere@tdpr.fr" }, bank_account: { account_holder_name: "Jean-Baptiste Poquelin", iban: "FR14BARC20000055779911" }, # Amendment details are required for SEPA only amendment: { original_mandate_reference: "REFNMANDATE", original_creditor_id: "FR123OTHERBANK", original_creditor_name: "Amphitryon" } }) ``` ```java MandateImportEntry mandateImportEntry = client.mandateImportEntries().create() .withCustomerCompanyName("Théâtre du Palais-Royal") .withCustomerEmail("moliere@tdpr.fr") .withBankAccountAccountHolderName("Jean-Baptiste Poquelin") .withBankAccountIban("FR14BARC20000055779911") // Amendment details are required for SEPA only .withAmendmentOriginalMandateReference("REFNMANDATE") .withAmendmentOriginalCreditorId("FR123OTHERBANK") .withAmendmentOriginalCreditorName("Amphitryon") .withLinksMandateImport(mandateImport.getId()) .execute(); ``` ```javascript const request = { customer: { company_name: "Théâtre du Palais-Royal", email: "moliere@tdpr.fr", }, bank_account: { account_holder_name: "Jean-Baptiste Poquelin", iban: "FR14BARC20000055779911", }, // Amendment details are required for SEPA only amendment: { original_mandate_reference: "REFNMANDATE", original_creditor_id: "FR123OTHERBANK", original_creditor_name: "Amphitryon", }, links: { mandate_import: mandateImport.id, }, }; const mandateImportEntry = await client.mandateImportEntries.create(request); ``` ```net var request = new GoCardless.Services.MandateImportEntryCreateRequest() { Customer = new GoCardless.Services.MandateImportEntryCreateRequest.MandateImportEntryCustomer() { CompanyName = "Théâtre du Palais-Royal" Email = "moliere@tdpr.fr" } BankAccount = new GoCardless.Services.MandateImportEntryCreateRequest.MandateImportEntryBankAccount() { AccountHolderName = "Jean-Baptiste Poquelin" Iban = "FR14BARC20000055779911" } // Amendment details are required for SEPA only Amendment = new GoCardless.Services.MandateImportEntryCreateRequest.MandateImportEntryAmendment() { OriginalMandateReference = "REFNMANDATE" OriginalCreditorId = "FR123OTHERBANK" OriginalCreditorName = "Amphitryon" } Links = new GoCardless.Services.MandateImportEntryCreateRequest.MandateImportEntryLinks() { MandateImport = mandateImport.Id } }; var importResponse = await gocardless.MandateImportEntries.CreateAsync(request); GoCardless.Resources.MandateImportEntry entry = importResponse.MandateImportEntry; ``` ```go ctx := context.TODO() mandateImportEntryCreateParams := gocardless.MandateImportEntryCreateParams{ Customer: gocardless.MandateImportEntryCreateParamsCustomer{ CompanyName: "Théâtre du Palais-Royal", Email: "moliere@tdpr.fr", }, BankAccount: gocardless.MandateImportEntryCreateParamsBankAccount{ AccountHolderName: "Jean-Baptiste Poquelin", Iban: "FR14BARC20000055779911", }, Amendment: &gocardless.MandateImportEntryCreateParamsAmendment{ OriginalMandateReference: "REFMANDATE", OriginalCreditorId: "FR123OTHERBANK", OriginalCreditorName: "Amphitryon", }, Links: gocardless.MandateImportEntryCreateParamsLinks{ MandateImport: "MandateImportId", }, } client.MandateImportEntries().Create(ctx, mandateImportEntryCreateParams) ``` ```http POST https://api.gocardless.com/mandate_import_entries HTTP/1.1 { "mandate_import_entries": { "links": { "mandate_import": "IM000010790WX1" }, "record_identifier": "bank-file.xml/line-1", "customer": { "company_name": "Théâtre du Palais-Royal", "email": "moliere@tdpr.fr" }, "bank_account": { "account_holder_name": "Jean-Baptiste Poquelin", "iban": "FR14BARC20000055779911" }, "amendment": { "original_mandate_reference": "REFNMANDATE", "original_creditor_id": "FR123OTHERBANK", "original_creditor_name": "Amphitryon" } } } HTTP/1.1 201 (Created) { "mandate_import_entries": { "record_identifier": "bank-file.xml/line-1", "created_at": "2018-03-03T00:00:00Z", "links": { "mandate_import": "IM000010790WX1" } } } ``` Repeat for each mandate. If you provide invalid data, the API returns a descriptive error for that entry — fix it and retry before submitting. SEPA example with amendment details: ```http curl -X POST https://api.gocardless.com/mandate_import_entries \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "mandate_import_entries": { "links": { "mandate_import": "IM123" }, "record_identifier": "your-internal-customer-id-456", "customer": { "company_name": "Théâtre du Palais-Royal", "email": "moliere@tdpr.fr" }, "bank_account": { "account_holder_name": "Jean-Baptiste Poquelin", "iban": "FR14BARC20000055779911" }, "amendment": { "original_mandate_reference": "REFNMANDATE", "original_creditor_id": "FR123OTHERBANK", "original_creditor_name": "Amphitryon" } } } ``` ### Submit for Review Once all entries are added, submit the import. All imports are reviewed by GoCardless before processing to prevent fraudulent use. ```php $client->mandateImports()->submit($mandateImport->id); ``` ```python client.mandate_imports.submit(mandate_import.id) ``` ```ruby @client.mandate_imports.submit(mandate_import.id) ``` ```java client.mandateImports().submit(mandateImport.getId()).execute(); ``` ```javascript await client.mandateImports.submit(mandateImport.id); ``` ```net await gocardless.MandateImports.SubmitAsync(mandateImport.Id); ``` ```go ctx := context.TODO() mandateImportSubmitParams := goCardless.MandateImportSubmitParams{} client.MandateImports().Submit(ctx, mandateImport.Id, mandateImportSubmitParams) ``` ```http POST https://api.gocardless.com/mandate_imports/IM000010790WX1/actions/submit HTTP/1.1 HTTP/1.1 200 (OK) { "mandate_imports": { "id": "IM000010790WX1", "scheme": "bacs", "status": "submitted", "created_at": "2018-03-12T14:03:04.000Z" } } ``` > **Info: Need to cancel?** > You can cancel a submitted import before it is approved using the [cancellation API]. Once > approved, an import cannot be reversed. ### Await Approval GoCardless reviews all submitted imports before processing. During this time the import status will be submitted. Common reasons for rejection: - Entries contain invalid or mismatched bank details - SEPA amendment details are missing or incorrect - The scheme specified doesn't match the bank accounts provided If your import is rejected, GoCardless will contact you with details. You'll need to create a new import with corrected entries. ### Reconcile your records When the import is approved, GoCardless processes the mandates. You'll receive webhooks as each mandate is created, the same events as mandates created through the standard API: | **Event** | **Meaning** | | ----------------- | -------------------------------------------------------- | | `mandate.created` | Mandate successfully imported | | `mandate.active` | Mandate active and ready to collect against | | `mandate.failed` | Mandate could not be created (e.g. invalid bank details) | To map your internal records to the new GoCardless IDs, retrieve the entries once the import status is processed. Match each entry using the `record_identifier` you set in Step 2: ```php $entries = $client->mandateImportEntries()->all([ "params" => ["mandate_import" => "IM000010790WX1"] ]); foreach ($entries as $i => $entry) { echo $entry->record_identifier; echo $entry->links->customer; echo $entry->links->customer_bank_account; echo $entry->links->mandate; } ``` ```python response = client.mandate_import_entries.all( params={ "mandate_import": mandate_import.id } ).records for entry in records: print(entry.record_identifier) print(entry.links.customer) print(entry.links.customer_bank_account) print(entry.links.mandate) ``` ```ruby @client.mandate_import_entries.all( params: { "mandate_import" => mandate_import.id } ).each do |entry| puts entry.record_identifier puts entry.links.customer puts entry.links.customer_bank_account puts entry.links.mandate end ``` ```java for (MandateImportEntry entry : client.mandateImportEntries().all().withMandateImport("IM000010790WX1").execute()) { System.out.println(entry.getRecordIdentifier()); System.out.println(entry.getLinks().getCustomer()); System.out.println(entry.getLinks().getCustomerBankAccount()); System.out.println(entry.getLinks().getMandate()); } ``` ```javascript const request = { mandate_import: mandateImport.id, }; for await (let entry of client.mandateImportEntries.all(request)) { console.log(entry.record_identifier); console.log(entry.links.customer); console.log(entry.links.customer_bank_account); console.log(entry.links.mandate); } ``` ```net var request = new GoCardless.Services.MandateImportEntryListRequest() { MandateImport = mandateImport.Id }; var response = gocardless.MandateImportEntries.All(request); foreach (GoCardless.Resources.MandateImportEntry entry in response) { Console.WriteLine(entry.RecordIdentifier); Console.WriteLine(entry.Links.Customer); Console.WriteLine(entry.Links.CustomerBankAccount); Console.WriteLine(entry.Links.Mandate); } ``` ```go ctx := context.TODO() mandateImportEntryListParams := goCardless.MandateImportEntryListParams{ MandateImport: "IM000010790WX1", } mandateImportEntries, err := client.MandateImportEntries().List(ctx, mandateImportEntryListParams) if err != nil { fmt.Println("err is %s", err.Error()) } for entry := range mandateImportEntries { fmt.Println(entry.RecordIdentifier) fmt.Println(entry.Links.Customer) fmt.Println(entry.Links.CustomerBankAccount) fmt.Println(entry.Links.Mandate) } ``` ```http GET https://api.gocardless.com/mandate_import_entries?mandate_import=IM000010790WX1 HTTP/1.1 HTTP/1.1 200 (OK) { "mandate_import_entries": [ { "record_identifier": "bank-file.xml/line-2", "created_at": "2018-03-03T00:00:01Z", "links": { "mandate_import": "IM000010790WX1", "customer": "CU456", "customer_bank_account": "BA456", "mandate": "MD456" } }, { "record_identifier": "bank-file.xml/line-1", "created_at": "2018-03-03T00:00:00Z", "links": { "mandate_import": "IM000010790WX1", "customer": "CU123", "customer_bank_account": "BA123", "mandate": "MD123" } } ], "meta": { "cursors": { "before": null, "after": null }, "limit": 50 } } ``` Use the mandate ID from each entry to start collecting payments. See [One-off payments](/docs/collect-payments/one-off-payments/one-off-direct-debit) and [Recurring payments](/docs/collect-payments/recurring-payments/subscriptions). ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create new mandates from scratch using the Billing Requests API. #### [One-off Direct Debit](/docs/collect-payments/one-off-payments/one-off-direct-debit) Collect one-off payments against your newly imported mandates. #### [Subscriptions](/docs/collect-payments/recurring-payments/subscriptions) Set up recurring subscription payments against imported mandates. #### [Mandate Events](/docs/collect-payments/events-and-webhooks/mandate-events) Handle mandate lifecycle webhooks as imported mandates become active. ## Instalment Schedules URL: https://docs.gocardless.com/docs/collect-payments/recurring-payments/instalment-schedules > Create instalment payment schedules. # Instalments ## What are Instalments? Spread the cost of a purchase over a defined number of fixed payments. You specify the total amount, number of instalments, and schedule; GoCardless handles the rest. - Payment plans for high-ticket purchases - Tuition and course fees - Professional services (accounting, legal) - Healthcare and dental treatment plans ## Comparison between other recurring payment options **Key difference from subscriptions:** Instalment schedules have a defined end. Subscriptions continue indefinitely until cancelled. | | Subscriptions | Instalments | Variable Recurring Payments | Instant Bank Pay + Direct Debit | | ---------------------- | ---------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------- | | Mandate required | Yes | Yes | Yes (consent) | Yes | | Customer authorisation | Once | Once | Once (with agreed limits and frequency) | Once | | Payment amounts | Fixed (per subscription) | Fixed per instalment, can vary across schedule | Variable within agreed constraints | First payment fixed; subsequent payments flexible | | Payment schedule | Merchant-defined recurring (weekly, monthly, yearly) | Merchant-defined schedule with a defined end | Flexible - merchant triggers payments as needed | Flexible after first payment | | Confirmation speed | 2-x business days | 2-x business days | Seconds | First payment: minutes; subsequent: 2-x business days | | Chargeback risk | Yes | Yes | None | First payment: none; subsequent: yes | | Missed payment retries | Yes (with Success+) | Yes (with Success+) | Yes | Subsequent payments: yes | | Best for | SaaS, memberships, gym fees, insurance | Payment plans, tuition, professional services | Usage-based regulated billing and utilities, financial services, government services | Subscription services needing immediate, initial payment | | Availability | All schemes | All schemes | GBP only | GBP and EUR | ## How it works 1. The customer sets up a mandate 2. You create an instalment schedule specifying the total amount, the number of payments, and the frequency 3. GoCardless automatically creates and collects each instalment 4. The schedule completes after the final instalment **Frequency options:** Weekly, monthly, yearly, or custom intervals. ## Step-by-step guide ### Create a billing request ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'mandate_request': { 'scheme': 'bacs', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { mandate_request: { scheme: 'bacs' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "pending", "mandate_request": { "currency": "GBP", "scheme": "bacs" } } } ``` ### Confirm the mandate After creating the Billing Request, direct the customer to authorise the mandate. How you do this depends on your integration type: - Hosted Pages - Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Payment Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages). - Custom API - Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). ### Handle the outcome Once fulfilled, retrieve both mandate ID and payment ID from the billing request: ```http curl https://api.gocardless.com/billing_requests/BRQ000123 \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->get('BRQ000123'); $mandateId = $response->mandate_request->links->mandate; ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests() .get("BRQ000123") .execute(); String mandateId = billingRequest.getMandateRequest().getLinks().getMandate(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const billingRequest = await client.billingRequests.find("BRQ000123"); const mandateId = billingRequest.mandate_request.links.mandate; ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var billingRequest = await client.BillingRequests.GetAsync("BRQ000123"); var mandateId = billingRequest.MandateRequest.Links.Mandate; ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } billingRequest, err := client.BillingRequests.Get(context.TODO(), "BRQ000123") if err != nil { panic(err) } mandateId := billingRequest.MandateRequest.Links.Mandate fmt.Println(mandateId) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "fulfilled", "mandate_request": { "scheme": "bacs", "links": { "mandate": "MD123" } } } } ``` Listen for webhooks to confirm the payment status: | Event | Meaning | | ------------------------- | -------------------------------- | | billing_request_fulfilled | Customer authorised the mandate | | mandates_created | Mandate created and ready to use | | mandates_active | Mandate active | ### Setup the instalments Once the mandate is active, set up recurring payments against it. **Option A** - Create the instalment plan with fixed dates (you specify each exact charge date): ```http curl -X POST https://api.gocardless.com/instalment_schedules \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "instalment_schedules": { "name": "Invoice #1234", "currency": "GBP", "total_amount": 2500, "instalments": [ { "amount": 1500, "charge_date": "2024-11-01" }, { "amount": 1000, "charge_date": "2025-02-01" } ], "links": { "mandate": "MD123" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->instalmentSchedules()->createWithDates([ 'params' => [ 'name' => 'Invoice #1234', 'currency' => 'GBP', 'total_amount' => 2500, 'instalments' => [ ['amount' => 1500, 'charge_date' => '2024-11-01'], ['amount' => 1000, 'charge_date' => '2025-02-01'], ], 'links' => [ 'mandate' => 'MD123', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.instalment_schedules.create_with_dates( params={ 'name': 'Invoice #1234', 'currency': 'GBP', 'total_amount': 2500, 'instalments': [ {'amount': 1500, 'charge_date': '2024-11-01'}, {'amount': 1000, 'charge_date': '2025-02-01'}, ], 'links': { 'mandate': 'MD123', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.instalment_schedules.create_with_dates( params: { name: 'Invoice #1234', currency: 'GBP', total_amount: 2500, instalments: [ { amount: 1500, charge_date: '2024-11-01' }, { amount: 1000, charge_date: '2025-02-01' }, ], links: { mandate: 'MD123' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); InstalmentSchedule instalmentSchedule = client.instalmentSchedules() .createWithDates() .withName("Invoice #1234") .withCurrency("GBP") .withTotalAmount(2500) .withInstalment(1500, "2024-11-01") .withInstalment(1000, "2025-02-01") .withLinksMandate("MD123") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const instalmentSchedule = await client.instalmentSchedules.createWithDates({ name: "Invoice #1234", currency: "GBP", total_amount: 2500, instalments: [ { amount: 1500, charge_date: "2024-11-01" }, { amount: 1000, charge_date: "2025-02-01" }, ], links: { mandate: "MD123", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var instalmentSchedule = await client.InstalmentSchedules.CreateWithDatesAsync( new InstalmentScheduleCreateWithDatesRequest { Name = "Invoice #1234", Currency = "GBP", TotalAmount = 2500, Instalments = new List { new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleInstalments { Amount = 1500, ChargeDate = "2024-11-01" }, new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleInstalments { Amount = 1000, ChargeDate = "2025-02-01" } }, Links = new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleLinks { Mandate = "MD123" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.InstalmentScheduleCreateWithDatesParams{ Name: "Invoice #1234", Currency: "GBP", TotalAmount: 2500, Instalments: []gocardless.InstalmentScheduleCreateWithDatesParamsInstalments{ {Amount: 1500, ChargeDate: "2024-11-01"}, {Amount: 1000, ChargeDate: "2025-02-01"}, }, Links: gocardless.InstalmentScheduleCreateWithDatesParamsLinks{ Mandate: "MD123", }, } instalmentSchedule, err := client.InstalmentSchedules.CreateWithDates(context.TODO(), params) if err != nil { panic(err) } fmt.Println(instalmentSchedule) } ``` **Option B** - Create the instalment plan with regular intervals (GoCardless calculates the dates): ```http curl -X POST https://api.gocardless.com/instalment_schedules \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "instalment_schedules": { "name": "Invoice #1234", "currency": "GBP", "total_amount": 2500, "instalments": { "start_date": "2024-11-01", "interval_unit": "monthly", "interval": 1, "amounts": [1500, 1000] }, "links": { "mandate": "MD123" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->instalmentSchedules()->createWithSchedule([ 'params' => [ 'name' => 'Invoice #1234', 'currency' => 'GBP', 'total_amount' => 2500, 'instalments' => [ 'start_date' => '2024-11-01', 'interval_unit' => 'monthly', 'interval' => 1, 'amounts' => [1500, 1000], ], 'links' => [ 'mandate' => 'MD123', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.instalment_schedules.create_with_schedule( params={ 'name': 'Invoice #1234', 'currency': 'GBP', 'total_amount': 2500, 'instalments': { 'start_date': '2024-11-01', 'interval_unit': 'monthly', 'interval': 1, 'amounts': [1500, 1000], }, 'links': { 'mandate': 'MD123', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.instalment_schedules.create_with_schedule( params: { name: 'Invoice #1234', currency: 'GBP', total_amount: 2500, instalments: { start_date: '2024-11-01', interval_unit: 'monthly', interval: 1, amounts: [1500, 1000] }, links: { mandate: 'MD123' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); InstalmentSchedule instalmentSchedule = client.instalmentSchedules() .createWithSchedule() .withName("Invoice #1234") .withCurrency("GBP") .withTotalAmount(2500) .withInstalmentsStartDate("2024-11-01") .withInstalmentsIntervalUnit("monthly") .withInstalmentsInterval(1) .withInstalmentsAmounts(Arrays.asList(1500, 1000)) .withLinksMandate("MD123") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const instalmentSchedule = await client.instalmentSchedules.createWithSchedule({ name: "Invoice #1234", currency: "GBP", total_amount: 2500, instalments: { start_date: "2024-11-01", interval_unit: "monthly", interval: 1, amounts: [1500, 1000], }, links: { mandate: "MD123", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var instalmentSchedule = await client.InstalmentSchedules.CreateWithScheduleAsync( new InstalmentScheduleCreateWithScheduleRequest { Name = "Invoice #1234", Currency = "GBP", TotalAmount = 2500, Instalments = new InstalmentScheduleCreateWithScheduleRequest.InstalmentScheduleInstalments { StartDate = "2024-11-01", IntervalUnit = InstalmentScheduleCreateWithScheduleRequest.InstalmentScheduleInstalments.InstalmentScheduleInstalmentsIntervalUnit.Monthly, Interval = 1, Amounts = new List { 1500, 1000 } }, Links = new InstalmentScheduleCreateWithScheduleRequest.InstalmentScheduleLinks { Mandate = "MD123" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.InstalmentScheduleCreateWithScheduleParams{ Name: "Invoice #1234", Currency: "GBP", TotalAmount: 2500, Instalments: gocardless.InstalmentScheduleCreateWithScheduleParamsInstalments{ StartDate: "2024-11-01", IntervalUnit: "monthly", Interval: 1, Amounts: []int{1500, 1000}, }, Links: gocardless.InstalmentScheduleCreateWithScheduleParamsLinks{ Mandate: "MD123", }, } instalmentSchedule, err := client.InstalmentSchedules.CreateWithSchedule(context.TODO(), params) if err != nil { panic(err) } fmt.Println(instalmentSchedule) } ``` **Response:** ```json { "instalment_schedules": { "id": "IS123", "status": "active", "name": "Invoice #1234", "currency": "GBP", "total_amount": 2500, "links": { "mandate": "MD123", "payments": ["PM001", "PM002"] } } } ``` ### Manage the instalment plan Listen for webhooks to confirm the mandate status and notifications about future instalments: | **Event** | **Meaning** | | ------------------------------ | ----------------------------------------- | | instalment_schedules_created | Schedule created, all payments queued | | payments_confirmed | Individual payment collected successfully | | payments_failed | Individual payment failed | | instalment_schedules_completed | All payments in the schedule collected | | instalment_schedules_errored | One or more payments failed | You can cancel the instalment plan: ```http curl -X POST https://api.gocardless.com/instalment_schedules/IS123/actions/cancel \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php $response = $client->instalmentSchedules()->cancel('IS123'); ``` ```python response = client.instalment_schedules.cancel('IS123') ``` ```ruby response = client.instalment_schedules.cancel('IS123') ``` ```java InstalmentSchedule instalmentSchedule = client.instalmentSchedules() .cancel("IS123") .execute(); ``` ```javascript const instalmentSchedule = await client.instalmentSchedules.cancel("IS123"); ``` ```cs var instalmentSchedule = await client.InstalmentSchedules.CancelAsync("IS123"); ``` ```go instalmentSchedule, err := client.InstalmentSchedules.Cancel(context.TODO(), "IS123", gocardless.InstalmentScheduleCancelParams{}) ``` ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates and collect bank account details via the API. #### [Subscriptions](/docs/collect-payments/recurring-payments/subscriptions) Collect a fixed amount on a regular schedule against an active mandate. #### [Instalment Schedule Events](/docs/api-reference/events/instalment-schedule) Understand the webhook events fired during instalment schedule lifecycle. #### [Success+](/docs/optimise/reduced-failed-payments-with-success-plus) Automatically retry failed instalment payments. ## Instant First Payment with Mandate URL: https://docs.gocardless.com/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate > Take an instant first payment while setting up a Direct Debit mandate. # Instant Payment with Direct Debit Setup ## What are Instant Payment with Direct Debit Setup? Take an immediate payment via Instant Bank Pay while automatically setting up a Direct Debit mandate for future payments. This gives you the speed of instant confirmation for the first payment and the flexibility of Direct Debit for ongoing charges. **Integration options:** This guide shows the API flow. You can also use [Hosted Payment Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) for a no-code approach. Drop-in Flow does not support Instant Bank Pay. **Availability:** GBP (Faster Payments), EUR (SEPA Instant) **When to use this combined flow** - Subscription services requiring immediate activation - Sign-up fee plus ongoing billing (e.g., gym membership) - Trial conversions with instant first charge - Any service where you need payment confirmation before providing access ## Comparison between other recurring payment options | | Subscriptions | Instalments | Variable Recurring Payments | Instant Bank Pay + Direct Debit | | ---------------------- | ---------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------- | | Mandate required | Yes | Yes | Yes (consent) | Yes | | Customer authorisation | Once | Once | Once (with agreed limits and frequency) | Once | | Payment amounts | Fixed (per subscription) | Fixed per instalment, can vary across schedule | Variable within agreed constraints | First payment fixed; subsequent payments flexible | | Payment schedule | Merchant-defined recurring (weekly, monthly, yearly) | Merchant-defined schedule with a defined end | Flexible - merchant triggers payments as needed | Flexible after first payment | | Confirmation speed | 2-x business days | 2-x business days | Seconds | First payment: minutes; subsequent: 2-x business days | | Chargeback risk | Yes | Yes | None | First payment: none; subsequent: yes | | Missed payment retries | Yes (with Success+) | Yes (with Success+) | Yes | Subsequent payments: yes | | Best for | SaaS, memberships, gym fees, insurance | Payment plans, tuition, professional services | Usage-based regulated billing and utilities, financial services, government services | Subscription services needing immediate, initial payment | | Availability | All schemes | All schemes | GBP only | GBP and EUR | ## How it works 1. Customer authorises an instant payment and a Direct Debit mandate in a single flow 2. The instant payment is confirmed within minutes 3. The Direct Debit mandate is set up for future payments 4. You can then collect recurring or one-off payments against the mandate ## Step-by-step guide ### Create a billing request ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "payment_request": { "description": "First payment", "amount": 5000, "currency": "GBP", "scheme": "faster_payments" }, "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'payment_request' => [ 'description' => 'First payment', 'amount' => 5000, 'currency' => 'GBP', 'scheme' => 'faster_payments', ], 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'payment_request': { 'description': 'First payment', 'amount': 5000, 'currency': 'GBP', 'scheme': 'faster_payments', }, 'mandate_request': { 'scheme': 'bacs', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { payment_request: { description: 'First payment', amount: 5000, currency: 'GBP', scheme: 'faster_payments' }, mandate_request: { scheme: 'bacs' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withPaymentRequestDescription("First payment") .withPaymentRequestAmount(5000) .withPaymentRequestCurrency("GBP") .withPaymentRequestScheme("faster_payments") .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ payment_request: { description: "First payment", amount: 5000, currency: "GBP", scheme: "faster_payments", }, mandate_request: { scheme: "bacs", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { PaymentRequest = new BillingRequestCreateRequest.BillingRequestPaymentRequest { Description = "First payment", Amount = 5000, Currency = "GBP", Scheme = "faster_payments" }, MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ PaymentRequest: &gocardless.BillingRequestCreateParamsPaymentRequest{ Description: "First payment", Amount: 5000, Currency: "GBP", Scheme: "faster_payments", }, MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000303", "status": "pending", "payment_request": { "amount": 5000, "currency": "GBP", "scheme": "faster_payments" }, "mandate_request": { "scheme": "bacs", "currency": "GBP" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "collect_bank_account", "required": true, "completed": false }, { "type": "confirm_payer_details", "required": true, "completed": false }, { "type": "select_institution", "required": true, "completed": false }, { "type": "bank_authorisation", "required": true, "completed": false } ] } } ``` ### Confirm the mandate and payment After creating the Billing Request, direct the customer to authorise the mandate. How you do this depends on your integration type: - Hosted Pages - Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Payment Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages). - Custom API - Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). > **Warning:** > Don't use the redirect to confirm the outcome. Always use webhooks. ### Handle the outcome Once fulfilled, retrieve both mandate ID and payment ID from the billing request: ```http curl https://api.gocardless.com/billing_requests/BRQ000123 \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->get('BRQ000123'); $paymentId = $response->payment_request->links->payment; $mandateId = $response->mandate_request->links->mandate; ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.get('BRQ000123') payment_id = response.payment_request.links.payment mandate_id = response.mandate_request.links.mandate ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.get('BRQ000123') payment_id = response.payment_request.links.payment mandate_id = response.mandate_request.links.mandate ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests() .get("BRQ000123") .execute(); String paymentId = billingRequest.getPaymentRequest().getLinks().getPayment(); String mandateId = billingRequest.getMandateRequest().getLinks().getMandate(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const billingRequest = await client.billingRequests.find("BRQ000123"); const paymentId = billingRequest.payment_request.links.payment; const mandateId = billingRequest.mandate_request.links.mandate; ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var billingRequest = await client.BillingRequests.GetAsync("BRQ000123"); var paymentId = billingRequest.PaymentRequest.Links.Payment; var mandateId = billingRequest.MandateRequest.Links.Mandate; ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } billingRequest, err := client.BillingRequests.Get(context.TODO(), "BRQ000123") if err != nil { panic(err) } paymentId := billingRequest.PaymentRequest.Links.Payment mandateId := billingRequest.MandateRequest.Links.Mandate fmt.Println(paymentId, mandateId) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "fulfilled", "payment_request": { "links": { "payment": "PM123" } }, "mandate_request": { "links": { "mandate": "MD123" } } } } ``` Listen for webhooks to confirm the payment and mandate status: | Event | Meaning | | ------------------------- | ---------------------------------------------------------- | | billing_request_fulfilled | Customer authorised mandate and payment is being processed | | payments_confirmed | Payment confirmed and settled | | payments_failed | Payment failed (e.g., insufficient funds) | | mandates_active | Mandate active and ready for recurring payments | ### Set up recurring payments Once the mandate is active, set up recurring payments against it: ```http curl -X POST https://api.gocardless.com/subscriptions \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "subscriptions": { "amount": 5000, "currency": "GBP", "name": "Monthly subscription", "interval_unit": "monthly", "interval": 1, "start_date": "2024-11-01", "links": { "mandate": "MD123" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->subscriptions()->create([ 'params' => [ 'amount' => 2500, 'currency' => 'GBP', 'name' => 'Monthly Magazine', 'interval_unit' => 'monthly', 'interval' => 1, 'day_of_month' => 1, 'start_date' => '2024-11-01', 'links' => [ 'mandate' => 'MD123', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.subscriptions.create( params={ 'amount': 2500, 'currency': 'GBP', 'name': 'Monthly Magazine', 'interval_unit': 'monthly', 'interval': 1, 'day_of_month': 1, 'start_date': '2024-11-01', 'links': { 'mandate': 'MD123', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.subscriptions.create( params: { amount: 2500, currency: 'GBP', name: 'Monthly Magazine', interval_unit: 'monthly', interval: 1, day_of_month: 1, start_date: '2024-11-01', links: { mandate: 'MD123' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); Subscription subscription = client.subscriptions() .create() .withAmount(2500) .withCurrency("GBP") .withName("Monthly Magazine") .withIntervalUnit(Subscription.IntervalUnit.MONTHLY) .withInterval(1) .withDayOfMonth(1) .withStartDate("2024-11-01") .withLinksMandate("MD123") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const subscription = await client.subscriptions.create({ amount: 2500, currency: "GBP", name: "Monthly Magazine", interval_unit: "monthly", interval: 1, day_of_month: 1, start_date: "2024-11-01", links: { mandate: "MD123", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var subscription = await client.Subscriptions.CreateAsync( new SubscriptionCreateRequest { Amount = 2500, Currency = "GBP", Name = "Monthly Magazine", IntervalUnit = SubscriptionCreateRequest.SubscriptionIntervalUnit.Monthly, Interval = 1, DayOfMonth = 1, StartDate = "2024-11-01", Links = new SubscriptionCreateRequest.SubscriptionLinks { Mandate = "MD123" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.SubscriptionCreateParams{ Amount: 2500, Currency: "GBP", Name: "Monthly Magazine", IntervalUnit: "monthly", Interval: 1, DayOfMonth: 1, StartDate: "2024-11-01", Links: gocardless.SubscriptionCreateParamsLinks{ Mandate: "MD123", }, } subscription, err := client.Subscriptions.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(subscription) } ``` **Response:** ```json { "subscriptions": { "id": "SB123", "status": "active", "amount": 2500, "currency": "GBP", "interval": 1, "interval_unit": "monthly", "start_date": "2024-11-01", "upcoming_payments": [ { "charge_date": "2024-11-01", "amount": 2500 }, { "charge_date": "2024-12-01", "amount": 2500 } ], "links": { "mandate": "MD123" } } } ``` Listen for webhooks to confirm the mandate status and notifications about future payments: | **Event** | **Meaning** | | ----------------------------- | ---------------------------------------- | | subscriptions_created | Subscription set up successfully | | subscriptions_payment_created | A scheduled payment was created | | payments_confirmed | Recurring payment collected successfully | | payments_failed | Recurring payment failed | | subscriptions_cancelled | Subscription cancelled | ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates and collect bank account details via the API. #### [Subscriptions](/docs/collect-payments/recurring-payments/subscriptions) Collect a fixed amount on a regular schedule against an active mandate. #### [Payment Events](/docs/api-reference/events/payment) Understand the webhook events fired during payment and mandate lifecycle. #### [GoCardless Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) Use hosted pages for a no-code integration approach. ## JavaScript Drop-in Flow Overview URL: https://docs.gocardless.com/docs/collect-payments/integration-types/javascript-drop-in-flow > Overview of JavaScript Drop-in Flow payment setup. # JavaScript Drop-in Flow Embed a pre-built payment flow directly in your website. The customer completes mandate setup and payment authorisation without leaving your domain. Supports: **Direct Debit only.** Does not support Pay By Bank or Commercial VRP. For these payments, use [Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) or [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). For Bacs mandate setup embedded inline in your own page rather than as a modal, with deeper styling control, see [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components). ### Best for - Keeping customers on your site throughout the payment flow - Moderate customisation with less development than a full custom build - Modern web applications (React, Vue, etc.) - Balance between speed of implementation and control ## How it works - Create a Billing Request and Billing Request Flow via the API (same as Hosted Pages) - Include the GoCardless Drop-in JavaScript library on your page - Initialise the component with the flow ID - The component renders the payment flow inline on your page - Listen for completion events and webhooks ### Customisation - Style the component to match your brand colours and fonts - Control the container element and placement - Handle events (success, exit, error) in your application code ## Step-by-step guide ### Create a billing request The Billing Request defines what you're collecting. ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->create([ "params" => [ "mandate_request" => [ "scheme" => "bacs" ] ] ]); ```` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.create(params={ "mandate_request": { "scheme": "bacs" } }) ```` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.create( params: { mandate_request: { scheme: "bacs" } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests().create() .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequest = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var mandateRequest = new GoCardless.Services.BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs", }; var resp = await gocardless.BillingRequests.CreateAsync( new GoCardless.Services.BillingRequestCreateRequest() { MandateRequest = mandateRequest, } ); GoCardless.Resources.BillingRequest billingRequest = resp.BillingRequest; ``` ```http POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "bacs" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) config, err := gocardless.NewConfig(accessToken, opts) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCreateParams := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } billingRequest, err := client.BillingRequests.Create(context, billingRequestCreateParams) ``` ```cli gc create billing_request \ -d 'mandate_request[scheme]=bacs' ``` Response: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "payment_request": null, "mandate_request": { "currency": "GBP", "scheme": "bacs" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010PDF4WD", "mandate_request": "MRQ123", "organisation": "OR123" }, "actions": [ { "type": "collect_customer_details", "status": "pending" }, { "type": "collect_bank_account", "status": "pending" } ] } } ``` ### Create a billing request flow This generates the hosted URL where the customer completes authorisation. ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequestFlows()->create([ "params" => [ "redirect_uri" => "https://my-company.com/landing", "exit_uri" => "https://my-company.com/exit", "links" => [ "billing_request" => "BRQ000010NMDMH2" ] ] ]); ```` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_request_flows.create(params={ "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } }) ```` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_request_flows.create( params: { redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create() .withRedirectUri("https://my-company.com/landing") .withExitUri("https://my-company.com/exit") .withLinksBillingRequest("BRQ000010NMDMH2") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequestFlow = await client.billingRequestFlows.create({ redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequestFlows.CreateAsync( new GoCardless.Services.BillingRequestFlowCreateRequest() { RedirectUri = "https://my-company.com/landing", ExitUri = "https://my-company.com/exit", Links = new GoCardless.Services.BillingRequestFlowCreateRequest.BillingRequestFlowLinks { BillingRequest = "BRQ000010NMDMH2", }, } ); GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow; ``` ```http POST https://api.gocardless.com/billing_request_flows HTTP/1.1 { "billing_request_flows": { "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here"; opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(accessToken, opts) billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams{} billingRequestFlowCreateParams.RedirectUri = "https://my-company.com/landing" billingRequestFlowCreateParams.ExitUri = "https://my-company.com/exit" billingRequestFlowCreateParams.Links.BillingRequest = "BRQ000010NMDMH2" billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams) ``` ```cli gc create billing_request_flow \ -d "links[billing_request]= BRQ000010NMDMH2" \ -d 'redirect_uri=https://my-company.com/landing' \ -d 'exit_uri=https://my-company.com/exit' ``` Response: ```json { "billing_request_flows": { "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=", "lock_customer_details": false, "lock_bank_account": false, "auto_fulfil": true, "created_at": "2021-03-30T16:23:10.679Z", "expires_at": "2021-04-06T16:23:10.679Z", "redirect_uri": "https://my-company.com/completed", "links": { "billing_request": "BRQ123" } } } ``` ### Initialise the Drop-in Component Include the GoCardless Drop-in script on your page and initialise it with the billing_request_flow_id from the previous step. ```javascript
``` ### Handle Webhooks | Event | **Meaning** | What to do | | -------------------------- | ------------------------------------------- | -------------------------------------------------------- | | billing_requests.fulfilled | Customer completed the flow | Record the mandate_id from links.mandate_request_mandate | | mandates.active | Mandate is ready to collect against | Enable payment collection in your system | | payments.confirmed | A payment against the mandate was collected | Mark the associated period/invoice as paid | | payments.failed | A payment failed | Notify the customer, retry if appropriate | | mandates.cancelled | Mandate was cancelled | Stop future payment creation | #### Pre-collecting customer details If you already have the customer's name, email, and address, submit them before creating the flow. The hosted page skips those fields or locks them if you prefer. ### Collect customer details (optional) ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->collectCustomerDetails("BR123", [ "params" => [ "customer" => [ "email" => "paddington@bearthings.com" "given_name" => "Paddington", "family_name" => "Bear" ], "customer_billing_detail" => [ "address_line1" => "32 Windsor Gardens", "city" => "London", "postal_code" => "W9 3RG", "country_code" => "GB" ] ] ]); ```` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.collect_customer_details("BR123", params={ customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB", } }) ```` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_customer_details("BR123", { params: { customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB". } } }) ``` ```java @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_customer_details("BR123", { params: { customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB" } } }) ``` ```javascript const constants = require('gocardless-nodejs/constants'); const gocardless = require('gocardless-nodejs'); const client = gocardless('your_access_token_here', constants.Environments.Sandbox); const resp = await client.billingRequests.collectCustomerDetails("BR123", { customer: { email: "paddington@bearthings.com" given_name: "Paddington", family_name: "Bear", }, customer_billing_detail: { address_line1: "32 Windsor Gardens", city: "London", postal_code: "W9 3RG", country_code: "GB" } }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var customer = new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomer { Email = "paddington@bearthings.com", GivenName = "Paddington", FamilyName = "Bear", }; var customerBillingDetail =new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomerBillingDetail { AddressLine1 = "32 Windsor Gardens", City = "London", PostalCode = "W9 3RG", CountryCode = "GB", }; var resp = await gocardless.BillingRequests.CollectCustomerDetails("BR123", new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest { Customer = customer, CustomerBillingDetail = customerBillingDetail, }); ``` ```http POST /billing_requests/BRQ000010NMDMH2/actions/collect_customer_details HTTP/1.1 { "data": { "customer": { "email": "paddington@bearthings.com", "given_name": "Paddington", "family_name": "Bear" }, "customer_billing_detail": { "address_line1": "32 Windsor Gardens", "city": "London", "postal_code": "W9 3RG", "country_code": "GB" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCollectCustomerDetailsParams := gocardless.BillingRequestCollectCustomerDetailsParams{ Customer: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomer{ GivenName: "Paddington", FamilyName: "Bear", Email: "paddington@bearthings.com", }, CustomerBillingDetail: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomerBillingDetail{ AddressLine1: "32 Windsor Gardens", City: "London", PostalCode: "W9 3RG", CountryCode: "GB", }, } billingRequest, err := client.BillingRequests.CollectCustomerDetails(context, "BR123", billingRequestCollectCustomerDetailsParams) ``` **Response:** Updated Billing Request with collect_customer_details marked completed. ### Collect bank account (optional) ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->collectBankAccount("BRQ000010NMDMH2", [ "params" => [ "account_number" => "55779911", "branch_code" => "200000", "account_holder_name" => "Frank Osborne", "country_code" => "GB" ] ]); ```` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.collect_bank_account("BRQ000010NMDMH2", params={ account_number: "55779911", branch_code: "200000", account_holder_name: "Frank Osborne", country_code: "GB", }) ```` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_bank_account("BRQ000010NMDMH2", { params: { account_number: "55779911", branch_code: "200000", account_holder_name: "Frank Osborne", country_code: "GB", } }) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); client.billingRequests().collectBankAccount("BRQ000010NMDMH2") .withAccountNumber("55779911") .withBranchCode("200000") .withAccountHolderName("Frank Osborne") .withCountryCode("GB") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const resp = await client.billingRequests.collectBankAccount("BRQ000010NMDMH2", { account_number: "55779911", branch_code: "200000", account_holder_name: "Frank Osborne", country_code: "GB", }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequests.CollectBankAccountAsync("BRQ000010NMDMH2", new BillingRequestCollectBankAccountRequest { AccountNumber = "55779911", BranchCode = "200000", AccountHolderName = "Frank Osborne", CountryCode = "GB", }); ``` ```http POST /billing_requests/BRQ000010NMDMH2/actions/collect_bank_account HTTP/1.1 { "data": { "account_number": "11223344", "branch_code": "040004", "account_holder_name": "Paddington Bear", "country_code": "GB" } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCollectBankAccountParams := gocardless.BillingRequestCollectBankAccountParams{ BranchCode: "200000", CountryCode: "GB", AccountNumber: "55779911", AccountHolderName: "Frank Osborne", } billingRequest, err := client.BillingRequests.CollectBankAccount(context, "BRQ000010NMDMH2", billingRequestCollectBankAccountParams) ``` **Response:** Updated Billing Request with collect_bank_account marked completed. > **Info:** > When creating the Billing Request Flow, pass `lock_customer_details: true` and/or > `lock_bank_account: true` to prevent customers editing pre-filled values. ## What's next? #### [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) Embed mandate setup inline in your own page, with deeper styling control than the Drop-in modal. #### [Prefill Customer Details](/docs/optimise/prefill-customer-details) Skip form steps by supplying customer details before the drop-in loads. #### [GoCardless Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) Redirect to a GoCardless-hosted checkout — no frontend JavaScript required. #### [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages) Full API control for teams that want complete UX ownership. ## Managing Payments URL: https://docs.gocardless.com/docs/collect-payments/managing-payments/reconciling-payouts > Reconcile payouts and manage payment lifecycle. # Reconciling Payouts Periodically (usually once every working day), we'll pay out payments your user has collected to their nominated bank account. When this happens, a "payout" record will be created which represents the transfer of funds. We'll generally send a single payout each day for each currency a user collects in. However, we may split the funds into multiple payouts if there are a very large number of payments to payout. > **Warning:** > **Verification Required** It's worth noting that we will only start sending payouts once your user > has verified their account - we'll send them emails reminding them to do this, but you might want > to flag this in your UI, especially when they first connect their account, and perhaps afterwards > until they receive their first payout. We've made a suggestion about communicating this to your > users in our ["User experience" guide](/docs/partner-integrations/getting-your-users-verified). A payout will not necessarily only contain payments collected through your integration - it may contain others if your user is also using our API, the Dashboard or another integration. When a payout is sent to your user, you'll receive a webhook with `resource_type` "payouts" and `action` "paid". In addition, for each payment that has been paid out, we'll send webhooks with `resource_type` "payments" and `action` "paid_out". The `links[payout]` attribute of that webhook will include the ID of the payout the payment appears in. For more details on handling webhooks, see the ["Staying up-to-date with webhooks"](/docs/getting-started/stay-up-to-date-with-webhooks) section earlier in this guide. For the majority of integrations, that'll be enough. But some integrations (for example, accountancy software) will want to go further in understanding exactly what makes up a payout. If you want to do more complex reconciliation (for example to build a business's accounts), the best way to understand what's inside a payout is to use the [Payout Items API](/docs/api-reference/payout-item#get-all-payout-items-in-a-single-payout). ### Using the Payout Items API The Payout Items API lets you see the individual transactions that made up the total amount of a payout. You can think of a payout in terms of credits and debits. When we collect payment on your user's behalf, we add the money collected to their GoCardless balance - that's a credit. But there can also be debits against that balance - for example, GoCardless' fees, app fees that you charge for using your integration or deductions for chargebacks. When we make a payout, we bundle up all of the outstanding credits and debits into it and reset the user's balance to zero. > **Info:** > We'll only make a payout when a merchant's balance is positive. Imagine that a merchant's balance > is zero, and they make a refund of £5.00. Their balance is now **-£5.00**. They then collect > payment of £10.00. Their balance is **+£5.00**, so we'll send them a payout, which will bundle up > the refund and the successful payment into its Payout Items. For each item in a payout, we expose an `amount` (which will be positive for credit, or negative for a debit) and will be in the customer's currency (i.e the currency the payment was taken in), a `type` (which explains the reason for the credit or debit) and `links` to any relevant resources (usually a payment, `links.payment`). There are ten types of payout items: | **Type** | **Description** | **Credit or debit** | **Links** | | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | --------------------------------- | | Payment paid out (`payment_paid_out`) | A payment was successfully collected from a customer and is being passed on to your user | Credit | `links.payment` | | Payment failed (`payment_failed`) | A payment appeared to have been collected from a customer successfully, but then the bank told us that it had in fact failed, so it is being deducted | Debit | `links.payment` | | Payment charged back (`payment_charged_back`) | A payment was successfully collected from a customer, but then the customer contacted their bank to reverse the transaction, so it is being deducted | Debit | `links.payment` | | Payment refunded (`payment_refunded`) | A payment was successfully collected from a customer, and then partially or fully refunded at your user's request, so the refunded amount is being deducted | Debit | `links.payment` , `links.mandate` | | GoCardless fee (`gocardless_fee`) | GoCardless deducted its transaction fee from an incoming payment or refunded its transaction fee when payment failed or was charged back | Credit/Debit | `links.payment` | | App fee (`app_fee`) | Partner integrations can add an "app fee" on top of GoCardless's fees. GoCardless deducted such a fee from an incoming payment or refunded it when payment failed or was charged back | Credit/Debit | `links.payment` | | Revenue share (`revenue_share`) | GoCardless paid out a commission to a partner for a successful payment or deducted it for a late failure or chargeback. Partner integrations can receive a share of GoCardless' fees when users collect payments through their integration. These do not appear in merchant payouts, since they are part of the `gocardless_fee`, but they will appear in partner payouts when they receive the commission. | Credit/Debit | `links.payment` | | Customer refunded (`refund`) | A refund was sent to a customer, not related to any particular payment, so the refunded amount is being deducted. | Debit | `links.mandate` | | Refund Funds returned (`refund_funds_returned`) | A refund made at your request, and previously deducted from a payout failed to reach the customer, so the refunded amount is being credited. | Credit | `links.payment` , `links.mandate` | | Surcharge fee (`surcharge_fee`) | GoCardless deducted a surcharge fee as the payment failed or was charged back, or refunded a surcharge fee as the bank or customer cancelled the chargeback. | Credit/Debit | `links.payment` | To see how these can fit together in the real world, let's imagine a payout as an example: | **Description** | **Type** | **Amount** | | ------------------------------------------------------- | ---------------------- | ---------- | | Payment successfully collected from Nick | `payment_paid_out` | +€20.00 | | App fee for payment collected from Nick | `gocardless_fee` | -€0.20 | | App fee for payment collected from Nick | `app_fee` | -€1.00 | | Refund issued for Andrew's payment, collected last week | `payment_refunded` | -€5.00 | | Bianca's payment from last week, which was charged back | `payment_charged_back` | -€10.00 | | Refund of GoCardless fee for charged back payment | `gocardless_fee` | +€0.10 | | Refund of app fee for charged back payment | `app_fee` | +€0.50 | | **Total** | **+€4.40** | | With the Payout Items API, you can look inside a payout and see the transactions that make it up, allowing you to, for example, "explain" transactions on your user's bank statement. When you receive a "payout paid" webhook (`resource_type` "payouts" and `action` "paid"), you can then query the Payout Items API: ```php $event->links['organisation']])->firstOrFail(); $client = new \GoCardlessPro\Client([ 'access_token' => $user->gocardless_access_token, 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $payout_id = $event->links['payout']; $payout = $client->payouts()->get($payout_id); echo $payout->amount; $payout_items = $client ->payoutItems() ->all(["params" => ["payout" => $payout_id]]); foreach ($payout_items as $payout_item) { echo $payout_item->amount; echo $payout_item->type; echo $payout_item->links->payment; } ``` ```python import os import gocardless_pro from myinvoicingapp.models import User #... def process_payout_event(self, event): user = User.object.get(gocardless_organisation_id=event['links']['organisation']) client = gocardless_pro.Client( access_token=user.gocardless_access_token, environment='sandbox' ) payout_id = event['links']['payout'] payout = client.payouts.get(payout_id) print payout.amount payout_items = client.payout_items.all( params={ "payout": payout_id } ).records for payout_item in payout_items: print payout_item.amount print payout_item.type print payout_item.links.payment ``` ```ruby require 'gocardless_pro' def process_payment_paid_out(event) user = User.find_by(gocardless_organisation_id: event.links.organisation) client = GoCardlessPro::Client.new( access_token: user.gocardless_access_token, environment: :sandbox ) payout_id = event.links.payout payout = client.payouts.find(payout_id) puts payout.amount client.payout_items.all(params: { payout: payout_id }).each do |payout_item| puts payout_item.amount puts payout_item.type puts payout_item.links.payment end end ``` ```java package com.myInvoicingApp; import com.gocardless.resources.Event; import com.gocardless.resources.Payout; import com.gocardless.resources.PayoutItem; import com.gocardless.GoCardlessClient; import com.myInvoicingApp.User; public class PayoutsWebhookHandler { public static void handlePayoutPaidEvent(Event event) { User user = User.getUserByGoCardlessID(event.getLinks().getOrganisation()); GoCardlessClient client = GoCardlessClient .newBuilder(user.gocardlessAccessToken) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); String payoutId = event.getLinks().getPayout(); Payout payout = client.payouts().get(payoutId).execute(); for (PayoutItem payoutItem : client.payoutItems().all().withPayout(payoutId).execute()) { System.out.println(payoutItem.getAmount()); System.out.println(payoutItem.getType()); System.out.println(payoutItem.getLinks().getPayment()); } } } ``` ```javascript const handlePayoutPaidEvent = async (eventResource) => { const payoutId = eventResource.links.payout; const payout = await client.payouts.find(payoutId); console.log(payout.id); const payoutItemsRequest = { payout: payoutId, }; for await (let payoutItem of client.payoutItems.all(payoutItemsRequest)) { console.log(payoutItem.amount); console.log(payoutItem.type); console.log(payoutItem.links.payment); } }; ``` ```net public void HandlePayoutPaidEvent(GoCardless.Resources.Event eventResource) { var user = db.Users.Single(user => user.GoCardlessID == eventResource.Links.Organisation); var client = GoCardlessClient.Create( user.GoCardlessAccessToken, GoCardlessClient.Environment.SANDBOX ); var payoutId = eventResource.Links.Payout; var payoutResponse = await client.Payouts.GetAsync(payoutId); var payout = paymentResponse.Payout; Console.WriteLine(payout.Id); var payoutItemsRequest = new GoCardless.Services.PayoutItemListRequest() { Payout = payoutId }; var payoutItems = client.PayoutItems.All(payoutItemsRequest); foreach (GoCardless.Resources.PayoutItem payoutItem in payoutItems) { Console.WriteLine(payoutItem.Amount); Console.WriteLine(payoutItem.Type); Console.WriteLine(payoutItem.Links.Payment); } } ``` ```go package main import ( "context" "fmt" "http" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } parseEvent := func(event gocardless.Event) { payoutId := event.Links.Payout ctx := context.TODO() payoutListParams := gocardless.PayoutItemListParams{ Payout: payoutId, } payoutItems, err := client.PayoutItems().All(ctx, payoutListParams) for _, payoutItem := range payoutItems { fmt.Println(payoutItem.Amount) fmt.Println(payoutItem.Type) fmt.Println(payoutItem.Links.Payment) } } http.HandleFunc("/webhookEndpoint", func(w http.ResponseWriter, r *http.Request) { wh, err := gocardless.NewWebhookHandler("secret", gocardless.EventHandlerFunc(func(event gocardless.Event) error { parseEvent(event) })) wh.ServeHTTP(w, r) }) } ``` For full details on the Payout Items API, head over to our [reference documentation](/docs/api-reference/payout-item). > **Info:** > **VAT Notice** GoCardless has been instructed by the relevant authorities to start charging VAT on > its fees. For more details and recommendations, head over to our > [guidelines](/docs/tutorials/handling-tax) ### Reconciling Payouts with Events When a payout is created not only does it have an event created for it, but all payments and refunds within that payout have events created for them too. If you know the payout's ID, you can fetch all of these events using two API requests. The first step is to find the "paid" event for the Payout you're interested in. You can do this by filtering events based on the ID of the payout and the action, which is "paid": ```http GET https://api.gocardless.com/events?payout=PY123&action=paid ``` To find child events for a payout, filter for events with a `parent_event` equal to the Payout's paid event: ```http GET https://api.gocardless.com/events?parent_event=EV123 ``` This will return a paginated list of all child events for payments and refunds associated with the payout. If you'd also like to return the associated payments or refunds, you can scope the request to a resource_type and include those resources: ```http GET https://api.gocardless.com/events?parent_event=EV123&resource_type=payments&include=payment GET https://api.gocardless.com/events?parent_event=EV123&resource_type=refunds&include=refund ``` ## What's next? #### [Payout Items API Reference](/docs/api-reference/payout-item) Full reference for the Payout Items API, including all item types. #### [FX Payments](/docs/collect-payments/managing-payments/fx) Reconcile payouts where payments were collected in a foreign currency. #### [Handling Tax](/docs/tutorials/handling-tax) GoCardless VAT guidance and recommendations for your integration. #### [Webhooks Overview](/docs/getting-started/stay-up-to-date-with-webhooks) Configure a webhook endpoint to receive payout and payment events in real time. ## Mandate Events URL: https://docs.gocardless.com/docs/collect-payments/events-and-webhooks/mandate-events > Handle mandate lifecycle events. # Mandate Events Mandate events are webhook notifications that GoCardless sends whenever a mandate's status changes. This guide covers the key events you should handle and what to do when they occur. A webhook is a request that GoCardless sends to your server to alert you of an event. Adding support for webhooks allows you to receive real-time notifications from GoCardless when things happen in your account, so you can take automated actions in response. > **Info:** > For a full list of mandate events see the [API reference](/docs/api-reference/events/mandate). For > general guidance on receiving and processing webhooks see [Webhooks > overview](/docs/getting-started/stay-up-to-date-with-webhooks). > **Info: Storing mandates** > Keep a mandates table in your database linked to your internal customer records. Store the > GoCardless mandate ID and status so you can track the full lifecycle and react to events. ## Mandate lifecycle A mandate moves through the following statuses: | **Status** | **Meaning** | | -------------------- | ------------------------------------------------------ | | `pending.submission` | Mandate created, not yet sent to the banks | | `submitted` | Sent to the banks for processing | | `active` | Confirmed by the banks, ready to collect against | | `failed` | Could not be set up (e.g. invalid bank details) | | `cancelled` | Cancelled by the customer, merchant, or GoCardless | | `expired` | Expired due to inactivity (scheme-dependent) | | `consumed` | Used for a one-off payment and can no longer be reused | ## Events to handle ### Mandate cancelled Mandates can be cancelled by the customer via their bank, by you via the API, or by GoCardless. When this happens you'll receive: ```json { "events": { "id": "EV123", "resource_type": "mandates", "action": "cancelled", "links": { "mandate": "MD123" }, "details": { "origin": "bank", "cause": "bank_account_closed", "description": "The bank account for this mandate has been closed." } } } ``` The `details.cause` field tells you why the mandate was cancelled. Common values: | **Cause** | **Meaning** | | -------------------------- | --------------------------------------------- | | `bank_account_closed` | Customer's bank account has been closed | | `invalid_bank_details` | Bank details were incorrect | | `direct_debit_not_enabled` | Account doesn't support Direct Debit | | `customer_approval_denied` | Customer cancelled at their bank | | `mandate_cancelled` | Cancelled via the GoCardless dashboard or API | When you receive this event you should: - Update the mandate status in your database - Prevent further payment attempts against this mandate - Notify the customer that their Direct Debit has been cancelled and prompt them to set up a new one if needed Cancelling a mandate yourself: If you need to cancel a mandate programmatically: ```php $currentUser->gocardlessAccessToken, 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $mandate = $client->mandates()->cancel($mandate_id); print("Status: " . $mandate->status); ``` ```python import gocardless_pro def cancel_mandate(current_user, mandate_id): client = gocardless_pro.Client( access_token=current_user.gocardless_access_token, environment='sandbox' ) mandate = client.mandates.cancel(mandate_id) print("Status: {}".format(mandate.status)) ``` ```ruby require 'gocardless_pro' def cancel_mandate(current_user, mandate_id) client = GoCardlessPro::Client.new( access_token: current_user.gocardless_access_token, environment: :sandbox ) mandate = client.mandates.cancel(mandate_id) puts "Status: #{mandate.status}" end ``` ```java package com.myInvoicingApp; import com.gocardless.GoCardlessClient; import com.gocardless.resources.Mandate; import com.myInvoicingApp.User; public class CancelMandate { public static void main(User currentUser, String mandateID) { GoCardlessClient client = GoCardlessClient .newBuilder(CurrentUser.gocardlessAccessToken) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); Mandate mandate = client.mandates().cancel(mandateID).execute(); System.out.printf("Status: %s%n", mandate.getStatus()); } } ``` ```javascript const mandateId = "MD0000123ABC"; console.log(`Cancelling mandate: ${mandateId}`); const mandate = await client.mandate.cancel(mandateId); console.log(`Status: ${mandate.status}`); ``` ```csharp const string mandateId = "MD0000123ABC"; Console.WriteLine($"Cancelling mandate: {mandateId}"); var cancelResponse = await client.Mandates.CancelAsync(mandateId); var mandate = cancelResponse.Mandate; Console.WriteLine($"Status: {mandate.Status}"); ``` ```go ctx := context.TODO() mandateCancelParams := gocardless.MandateCancelParams{} mandate, err := client.Mandates().Cancel(ctx, mandateId, mandateCancelParams) fmt.Printf("Status: %s%n", mandate.Status) ``` Only cancel a mandate if the customer has explicitly requested it. ### Mandate failed If the mandate cannot be set up; for example because the bank account doesn't support Direct Debit or has been closed, you'll receive: ```json { "events": { "id": "EV124", "resource_type": "mandates", "action": "failed", "links": { "mandate": "MD123" }, "details": { "origin": "bank", "cause": "bank_account_closed", "description": "The bank account for this mandate has been closed." } } } ``` When you receive this event you should: - Update the mandate status in your database - Notify the customer and prompt them to set up a new mandate with a different bank account Use `details.cause` to tailor your error message, the same cause values apply as for cancellations above ### Mandate expired Mandates can expire after a period of inactivity under certain schemes. Treat an expired event the same way as a cancelled event, update your records and prompt the customer to set up a new mandate if needed. ```json { "events": { "resource_type": "mandates", "action": "expired", "links": { "mandate": "MD123" } } } ``` ### Mandate replaced When a merchant enables the Merchant name on bank statement add-on, GoCardless moves their mandates from the GoCardless shared scheme identifier to the merchant's own identifier. For BACS mandates this results in a new mandate ID. You'll receive: ```json { "events": { "resource_type": "mandates", "action": "replaced", "links": { "mandate": "MD123", "new_mandate": "MD456" } } } ``` This requires immediate action. If you attempt to collect a payment against the old mandate ID you'll receive an `invalid_state` error with reason `mandate_replaced`. Update the mandate ID in your database to `links.new_mandate` as soon as you receive this event. ## Full list of mandate events For all possible mandate events and their details see the [API reference - mandate event types](/docs/api-reference/events/mandate). ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create the mandate your event handlers will track through its lifecycle. #### [Subscriptions](/docs/collect-payments/recurring-payments/subscriptions) Subscription payments depend on the mandate remaining active. #### [Billing Request Events](/docs/collect-payments/events-and-webhooks/billing-request-events) Events fired earlier in the lifecycle, during mandate creation via Billing Requests. #### [API Reference — Mandate Events](/docs/api-reference/events/mandate) Full list of mandate event types and their details. ## Multi-Currency & FX URL: https://docs.gocardless.com/docs/collect-payments/managing-payments/fx > Accept payments in multiple currencies with foreign exchange. # FX Payments ## What do I have to do to support payments with FX? This is a difficult question for us to answer, as it depends on how your specific integration works. The key things that are different from non-FX payments are: - A merchant can now collect payments in a currency for which they do not have a payout bank account. For some integrations, this may mean it's the first time merchants can collect in multiple currencies, which will have a UI impact - Payments and payouts might have associated FX information (i.e. an exchange rate) which you may need to use for reconciliation ## How do I know if FX is enabled? Call the [creditors](/docs/api-reference/creditor#get-a-single-creditor) endpoint for this merchant. If the field `fx_payout_currency` is set, then FX is enabled for this merchant. ## What currencies can a merchant collect money in? If FX is enabled, the merchant can collect money in any [supported currency](/docs/api-reference/schemes). ## How do I know which payments will have FX applied? There are two options, depending on when you need to know. 1. If a payment is going to be paid out in a different currency, there will be an `fx` object on the payment, with information about the exchange rate. 2. Call the [creditors](/docs/api-reference/creditor#list-creditors) endpoint for this merchant. By default, all payments will be paid out in the `fx_payout_currency`. However, the merchant may also collect in other currencies. These will be listed in the `links` section. In the below example, this merchant can collect in GBP and EUR, and all other currencies will be paid out in the `fx_payout_currency`. ```json "links": { "default_gbp_payout_account": "BA789", "default_eur_payout_account": "BA456" } ``` ## How do I tell the merchant what money they will receive? FX payments are not exchanged into the payout currency until the payout is transferred to the merchant. This means that until the payout has been paid out, we do not know what the exchange rate will be. Instead, we provide an `estimated_exchange_rate` in the `fx` block on both payments and payouts. You can display this as a 'best guess' until the actual exchange rate is fixed. Note that all items in a single payout will have the same original currency and exchange rate. ## How do I reconcile FX payouts? This very much depends on the implementation. However, if you are an accounting software or you do bank reconciliation, then you may want to think about the following. For these, we will use the example of a merchant with a GBP home currency collecting a EUR payment. We recommend you represent the flow of money to match the flow of funds: `EUR Payer -> EUR Clearing Account -> GBP payout account` You may have challenges if your software imposes a specific exchange rate, as the transfer into the GBP payout account must be correct to enable reconciliation. In this case, we recommend an alternative flow: `EUR Payer -> EUR Clearing Account -> GBP FX Suspense account -> GBP payout account` You can then calculate a 'correction' transaction to zero out the suspense account, which we would call _'realised FX gains/losses'_. Note that the `fx` block of both payments and payouts will have either an `estimated_exchange_rate` and an `exchange_rate`, depending on whether the exchange rate has been finalised or not. We recommend not doing any FX until the exchange_rate is confirmed, to help with reconciliation. ## How do I reconcile late failures, chargebacks and refunds for FX payments? As long as you have represented the payment as described above, this should not be a cause for concern. These are accounted for in the payouts API, so as long as you are using the `amount`, the `fx[amount]` and the `deducted_fees`, you should be able to avoid any more complexity. If a payment late fails, chargebacks or refunds, you should simply be able to move that money back out of the clearing account. The payout will then have that amount removed, and the `amount` and `fx[amount]` will be correct. ## What's next? #### [Reconciling Payouts](/docs/collect-payments/managing-payments/reconciling-payouts) Understand how payouts are structured and how to reconcile them using Payout Items. #### [Handling Tax](/docs/tutorials/handling-tax) GoCardless VAT guidance and recommendations for your integration. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create the mandate that FX payments are collected against. #### [Creditors API Reference](/docs/api-reference/creditor) Check the fx_payout_currency field to determine if FX is enabled for a merchant. ## Offline Mandates URL: https://docs.gocardless.com/docs/collect-payments/setting-up-mandates/offline-mandates > Set up mandates offline (paper or phone). # Offline Mandates Collecting your customer's payment authorisation via an online form isn't always possible. GoCardless also supports paper and phone authorisation collection (subject to regional availability). > **Info:** > This feature only applies to merchants on our Custom and self-serve Pro packages with the Custom > Payment Pages feature enabled. [Contact > support](https://support.gocardless.com/hc/en-gb/articles/360014292500-Paper-and-phone-authorisation) > to get this set up. [This page](https://support.gocardless.com/hc/en-gb/articles/360014292500-Paper-and-phone-authorisation) details the compliance requirements for collecting authorisation this way. Please read it before proceeding. ## Integration options There are two approaches you may take based on your current integration and future plans. 1. Billing Requests API: This is our newest API, which supports both bank debit and open banking use cases. Use it if you intend to build open banking functionality in future. 2. Core Endpoints: supports bank debit only. These are legacy API endpoints and do not support GoCardless' newest features such as Pay By Bank. Use them only if you're already integrated with them and don't intend to implement Pay By Bank. New integrations should use the Billing Requests API. ### Billing Requests API #### Billing Request Actions Whenever you create a Billing Request, it will have a list of `actions` that require completion before it's possible to fulfil the request. The possible actions are: - `choose_currency`, have the payer choose from a list of supported currencies - `collect_customer_details`, collect customer details required for the schemes - `collect_bank_account`, create the bank account for the mandate/payment - `confirm_payer_details`, confirm customer and bank account details provided by the payer Once all required actions have been completed, the Billing Request will become `ready_to_fulfil`, and an integrator can use the [fulfil](/docs/api-reference/billing-request#fulfil-a-billing-request) action to create all associated resources. #### Which actions should I implement? When [creating](/docs/api-reference/billing-request#create-a-billing-request) a Billing Request, the response will show you which actions you need to implement to complete it. We will also go through the actions you need to implement in the following steps. #### Ordering and control flow The actions presented on a Billing Request are unordered, but each action may have dependencies, or have other actions depending on it. These are specified in the fields `completes_actions` and `requires_actions`. Taking `collect_customer_details` as an example: ```json { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": ["choose_currency"], "status": "pending" } ``` **Action `status`:** is either `pending` or `completed`. **`requires_actions:`** Actions can only be executed if the actions listed in `requires_action` have been completed — in this example, we can't complete `collect_customer_details` until we've chosen the currency. **`completes_actions:`** Actions can complete other actions, which can help streamline checkout flows. In this example, collect_customer_details does not complete any other action as a side effect. For offline mandates, we suggest building the flow that process the actions in the order of: 1. `collect_customer_details`, requires the `choose_currency` action to be completed but this will be completed automatically when creating the ACH mandate via the Billing Request create API 2. `collect_bank_account`, collect the customer's bank account details 3. `confirm_payer_details`, as a scheme compliance rule it is required to crosscheck the details entered and confirm them #### Create an offline mandate via Billing Request API Create a Billing Request that specifies the type of mandate you wish to create via the `mandate_request` field. In this example, we are specifying the scheme as ACH which will default the currency to USD. For ACH specific mandates, you can provide the `authorisation_source` field to create an offline mandate. The `authorisation_source` field specifies the way in which the payer gave authorisation to the merchant. This is sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This field takes values of either `telephone`, `paper` or `web`. Use the [Create a Billing Request](/docs/api-reference/billing-request#create-a-billing-request) endpoint: ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->create([ "params" => [ "mandate_request" => [ "scheme" => "ach", "authorisation_source" => "telephone" ] ] ]); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.create(params={ "mandate_request": { "scheme": "ach", "authorisation_source": "telephone" } }) ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.create( params: { mandate_request: { scheme: "ach", authorisation_source: "telephone" } } ) ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests().create() .withMandateRequestScheme("ach") .withMandateRequestAuthorisationSource("telephone") .execute(); ``` ```javascript JavaScript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequest = await client.billingRequests.create({ mandate_request: { scheme: "ach", authorisation_source: "telephone", }, }); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var mandateRequest = new gocardless.BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "ach", AuthorisationSource = "telephone" }; var resp = await gocardless.BillingRequests.CreateAsync( new GoCardless.Services.BillingRequestCreateRequest() { MandateRequest = mandateRequest, } ); GoCardless.Resources.BillingRequest billingRequest = resp.BillingRequest; ``` ```http HTTP POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "ach", "authorisation_source": "telephone" } } } ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) config, err := gocardless.NewConfig(accessToken, opts) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCreateParams := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "ach", AuthorisationSource: "telephone", }, } billingRequest, err := client.BillingRequests.Create(context, billingRequestCreateParams) ``` ```bash CLI gc create billing_request \ -d 'mandate_request[scheme]=ach' \ -d 'mandate_request[authorisation_source]=telephone' ``` You'll receive a full Billing Request resource back. It will look like this, some detail omitted: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "payment_request": null, "mandate_request": { "currency": "USD", "scheme": "ach", "authorisation_source": "telephone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010PDF4WD", "mandate_request": "MRQ123", "organisation": "OR123" }, "actions": [ { "type": "collect_customer_details", "status": "pending" }, { "type": "collect_bank_account", "status": "pending" } ] } } ``` This completes the `choose_currency` action, and we can now continue with completing the rest of the Billing Request actions to set up this mandate. #### Action: `collect_customer_details` Billing Requests aim to create billing resources against a customer, either a mandate (Direct Debit, PayTo or VRPs), an Pay By Bank, or both. Payment schemes vary in what customer details you are required to collect. The `collect_customer_details` action is about collecting all the details required by either the mandate or the payment scheme, to ensure we meet regulatory needs. As an example, we can created a Billing Request for ACH scheme: ```http POST /billing_requests { "billing_requests": { "mandate_request": { "scheme": "ach", "authorisation_source": "telephone" } } } ``` This returns a Billing Request that looks like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": { "currency": "USD", "scheme": "ach", "authorisation_source": "telephone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010PDF4WD", "mandate_request": "MRQ123", "organisation": "OR123" }, "actions": [ { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": [ "choose_currency" ], "status": "pending", "collect_customer_details": { "incomplete_fields": { "customer": [ "email", "given_name", "family_name" ], "customer_billing_detail": [ "address_line1", "city", "postal_code", "country_code", "region", "ip_address" ] } } }, ..., ], "resources": { "customer": { "id": "CU00016WDAM7BS", "created_at": "2021-04-08T14:06:30.977Z", "email": null, "given_name": null, "family_name": null, "company_name": null, "language": "en", "phone_number": null, "metadata": {} }, "customer_billing_detail": { "id": "CBD000010PDF4WD", "created_at": "2021-04-08T14:06:30.997Z", "address_line1": null, "address_line2": null, "address_line3": null, "city": null, "region": null, "postal_code": null, "country_code": null, "swedish_identity_number": null, "danish_identity_number": null } } } } ``` Note that: - There is a `collect_customer_details` action, which is `pending` - A new customer has been created for us, as the Billing Request wasn't attached to an existing customer - The `customer` and `customer_billing_detail` resources are presented back to us, and they have no filled fields The `collect_customer_details` action is designed to help us collect the required information from our customers. Taking a closer look at the action: ```json { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": ["choose_currency"], "status": "pending", "collect_customer_details": { "incomplete_fields": { "customer": ["email", "given_name", "family_name"], "customer_billing_detail": [ "address_line1", "city", "postal_code", "country_code", "region", "ip_address" ] } } } ``` The `collect_customer_details.incomplete_fields` object tells us what fields we need to collect, for both resources. Which fields are required changes depending on the schemes of the mandate (or payment). We can complete this action by POST'ing to the [Collect customer details for the billing request](/docs/api-reference/billing-request#collect-customer-details) endpoint. Note that: - For online mandates with `"authorisation_source": "web"`, you will need to provide payer's `ip_address` as a result of their completion of a mandate setup flow in their browser. - For `paper` and `telephone` mandates, you will still need to provide an `ip_address` in the `customer_billing_detail`, however, this can just be a dummy `ip_address` (e.g. 192.0.0.0). ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->collectCustomerDetails("BR123", [ "params" => [ "customer" => [ "email" => "user@example.com", "given_name" => "Frank", "family_name" => "Osborne" ], "customer_billing_detail" => [ "address_line1" => "1 Somewhere Lane", "city" => "Los Angeles", "postal_code" => "90213", "country_code" => "US", "region" => "CA" "ip_address" => "192.0.2.1" ] ] ]); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.collect_customer_details("BR123", params={ customer: { email: "user@example.com" given_name: "Frank", family_name: "Osborne", }, customer_billing_detail: { address_line1: "27 Acer Road", city: "Los Angeles", postal_code: "90213", country_code: "US", region: "CA", ip_address: "192.0.2.1" } }) ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_customer_details("BR123", { params: { customer: { email: "user@example.com" given_name: "Frank", family_name: "Osborne", }, customer_billing_detail: { address_line1: "27 Acer Road", city: "Los Angeles", postal_code: "90213", country_code: "US", region: "CA", ip_address: "192.0.2.1" } } }) ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); client.billingRequests().collectCustomerDetails("BR123") .withCustomerEmail("user@example.com") .withCustomerGivenName("Frank") .withCustomerFamilyName("Osborne") .withCustomerBillingDetailAddressLine1("27 Acer Road") .withCustomerBillingDetailCity("Los Angeles") .withCustomerBillingDetailPostalCode("90213") .withCustomerBillingDetailCountryCode("US") .withCustomerBillingDetailRegion("CA") .withCustomerBillingDetailIpAddress("192.0.2.1") .execute(); ``` ```javascript JavaScript const constants = require('gocardless-nodejs/constants'); const gocardless = require('gocardless-nodejs'); const client = gocardless('your_access_token_here', constants.Environments.Sandbox); const resp = await client.billingRequests.collectCustomerDetails("BR123", { customer: { email: "user@example.com" given_name: "Frank", family_name: "Osborne", }, customer_billing_detail: { address_line1: "27 Acer Road", city: "Los Angeles", postal_code: "90213", country_code: "US", region: "CA", ip_address: "192.0.1.2" } }); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var customer = new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomer { Emil = "user@example.com" GivenName = "Frank", FamilyName = "Osborne", }; var customerBillingDetail = new new GoCardless.Services.BillingRequestCollectCustomerDetailsRequest.BillingRequestCustomerBillingDetail { AddressLine1 = "27 Acer Road", City = "Los Angeles", PostalCode = "90213", CountryCode = "US", Region = "CA", IpAddress = "192.0.1.2" }; var resp = await gocardless.BillingRequests.CollectCustomerDetails("BR123", new BillingRequestCollectCustomerDetailsRequest { Customer = customer, CustomerBillingDetail = customerBillingDetail, }); ``` ```http HTTP POST /billing_requests/BRQ123/actions/collect_customer_details HTTP/1.1 { "data": { "customer": { "email": "user@example.com", "given_name": "Frank", "family_name": "Osborne" }, "customer_billing_detail": { "address_line1": "27 Acer Road", "city": "Los Angeles", "postal_code": "90213", "country_code": "US", "region": "CA", "ip_address": "192.0.1.2" } } } ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCollectCustomerDetailsParams := gocardless.BillingRequestCollectCustomerDetailsParams{ Customer: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomer{ GivenName: "Frank", FamilyName: "Osborne", Email: "user@example.com", }, CustomerBillingDetail: &gocardless.BillingRequestCollectCustomerDetailsParamsCustomerBillingDetail{ AddressLine1: "27 Acer Road", City: "Los Angeles", PostalCode: "90213", CountryCode: "US", Region: "CA", IpAddress: "192.0.1.2" }, } billingRequest, err := client.BillingRequests.CollectCustomerDetails(context, "BR123", billingRequestCollectCustomerDetailsParams) ``` As with all action endpoints, the response is the Billing Request. What we get back is: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": { "scheme": "ach", "currency": "USD", "authorisation_source": "telephone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010PDF4WD", "organisation": "OR123", "mandate_request": "MRQ123" }, "actions": [ { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": [ "choose_currency" ], "status": "completed", "collect_customer_details": { "incomplete_fields": { "customer": [], "customer_billing_detail": [] } } }, ..., ], "resources": { "customer": { "id": "CU00016WDAM7BS", "created_at": "2021-04-08T14:06:30.977Z", "email": "user@example.com", "given_name": "Frank", "family_name": "Osborne", "company_name": null, "language": "en", "phone_number": null, "metadata": {} }, "customer_billing_detail": { "id": "CBD000010PDF4WD", "created_at": "2021-04-08T14:06:30.997Z", "address_line1": "27 Acer Road", "address_line2": null, "address_line3": null, "city": "Los Angeles", "region": null, "postal_code": "90213", "country_code": "US", "swedish_identity_number": null, "danish_identity_number": null } } } } ``` Note that: - The `collect_customer_details` action is now `completed`, meaning we can move on to other actions - As a result of us collecting the details, our `customer` and `customer_billing_detail` has been populated with the details we collected Most integrators will collect these details via web forms, filled by their payers. Integrators are expected to build forms that can collect all possible `customer` and `customer_billing_detail` fields (see the [Collect customer details](/docs/api-reference/billing-request#collect-customer-details) schema) but only display the inputs required, as per `incomplete_fields`. #### Action: collect_bank_account Depending on the scheme, we might need to collect bank account details before fulfilling the Billing Request. An example is a Direct Debit mandate, where we need to capture the payer's bank in order to create Direct Debit payments against them. As an example, we created a Billing Request for ACH scheme: ```http POST /billing_requests { "billing_requests": { "mandate_request": { "scheme": "ach", "authorisation_source": "telephone" } } } ``` This returns a Billing Request that looks like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": { "currency": "USD", "scheme": "ach", "authorisation_source": "telephone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010PDF4WD", "mandate_request": "MRQ123", "organisation": "OR123" }, "actions": [ { "type": "collect_bank_account", "required": true, "completes_actions": [ "choose_currency" ], "available_country_codes": [ "US" ], "requires_actions": [], "status": "pending" }, ..., ], } } ``` Note that: - There is a `collect_bank_account` action that is `pending` - We have no `links.customer_bank_account`, confirming no bank account is attached We can complete this action by POST'ing to the [Collect bank account for the billing request](/docs/api-reference/billing-request#collect-bank-account-details) endpoint: ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->collectBankAccount("BRQ000010NMDMH2", [ "params" => [ "account_number" => "2715500356", "bank_code" => "026073150", "account_holder_name" => "Frank Osborne", "country_code" => "US", "account_type": "checking" ] ]); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.collect_bank_account("BRQ000010NMDMH2", params={ account_number: "2715500356", bank_code: "026073150", account_holder_name: "Frank Osborne", country_code: "US", "account_type": "checking", }) ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.collect_bank_account("BRQ000010NMDMH2", { params: { account_number: "2715500356", bank_code: "026073150", account_holder_name: "Frank Osborne", country_code: "US", account_type: "checking", } }) ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); client.billingRequests().collectBankAccount("BRQ123") .withAccountNumber("2715500356") .withBankCode("026073150") .withAccountHolderName("Frank Osborne") .withCountryCode("US") .withAccountType("checking") .execute(); ``` ```javascript JavaScript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const resp = await client.billingRequests.collectBankAccount("BRQ123", { account_number: "2715500356", bank_code: "026073150", account_holder_name: "Frank Osborne", country_code: "US", account_type: "checking", }); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequests.CollectBankAccountAsync("BRQ123", new BillingRequestCollectBankAccountRequest { AccountNumber = "2715500356", BankCode = "026073150", AccountHolderName = "Frank Osborne", CountryCode = "US", AccountType = "checking", }); ``` ```http HTTP POST /billing_requests/BRQ123/actions/collect_bank_account HTTP/1.1 { "data": { "account_number": "2715500356", "bank_code": "026073150", "account_holder_name": "Frank Osborne", "country_code": "US", "account_type": "checking" } } ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCollectBankAccountParams := gocardless.BillingRequestCollectBankAccountParams{ BankCode: "026073150", CountryCode: "US", AccountNumber: "2715500356", AccountHolderName: "Frank Osborne", AccountType: "checking", } billingRequest, err := client.BillingRequests.CollectBankAccount(context, "BRQ123", billingRequestCollectBankAccountParams) ``` As with all action endpoints, the response is the Billing Request. What we get back is: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": { "currency": "USD", "scheme": "ach", "authorisation_source": "telephone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010P52VRF", "customer_bank_account": "BA123", "organisation": "OR123" }, "actions": [ { "type": "collect_bank_account", "required": true, "completes_actions": [ "choose_currency" ], "requires_actions": [], "status": "completed" }, ..., ], "resources": { "customer_bank_account": { "id": "BA123", "created_at": "2021-04-08T15:30:36.019Z", "account_number_ending": "56", "account_holder_name": "FRANK OSBORNE", "account_type": "checking", "bank_name": "Community Federal Savings Bank", "currency": "USD", "country_code": "US", "metadata": {}, "enabled": true, "links": { "customer": "CU00016WDAM7BS" } } } } } ``` Note that: - The `collect_bank_account` action is now `completed`, meaning we can move on to other actions - As a result of us collecting the bank account, we have created a `customer_bank_account` resource and you can see the `links.customer_bank_account` ID has been set #### Action: confirm_payer_details As part of scheme compliance, we need to ensure the payer was presented with a confirmation screen before fulfilling the Billing Request. All mandate requests will require this action. As an example, we created a Billing Request for ACH scheme: ```http POST /billing_requests { "billing_requests": { "mandate_request": { "scheme": "ach", "authorisation_source": "telephone" } } } ``` This returns a Billing Request that looks like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": { "currency": "USD", "scheme": "ach", "authorisation_source": "telephone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010PDF4WD", "mandate_request": "MRQ123", "organisation": "OR123" }, "actions": [ { "type": "confirm_payer_details", "required": true, "completes_actions": [], "requires_actions": [ "collect_customer_details", "collect_bank_account" ], "status": "pending" } ..., ], } } ``` Note that: - There is a `confirm_payer_details` action that is `pending` - The action is `required` — all mandate requests will require this - The action requires `collect_customer_details` and `collect_bank_account`, as we can only show the confirmation page once these actions are completed. We can complete this action by POST'ing to the [confirm payer details](/docs/api-reference/billing-request#confirm-the-payer-details) endpoint: ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->confirmPayerDetails("BR123"); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.confirm_payer_details("BR123") ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.confirm_payer_details("BR123") ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); client.billingRequests().confirmPayerDetails("BR123").execute(); ``` ```javascript JavaScript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const resp = await client.billingRequests.confirmPayerDetails("BR123"); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequests.ConfirmPayerDetailsAsync("BR123"); ``` ```http HTTP POST https://api.gocardless.com/billing_requests/BRQ123/actions/confirm_payer_details HTTP/1.1 ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestFulfilParams := gocardless.BillingRequestFulfilParams{} billingRequest, err := client.BillingRequests.Fulfil(context, "BR123", billingRequestFulfilParams) ``` As with all action endpoints, the response is the Billing Request. What we get back is: ```json { "billing_requests": { "id": "BRQ123", "status": "ready_to_fulfil", "mandate_request": { "currency": "USD", "scheme": "ach", "authorisation_source": "telephone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010P52VRF", "customer_bank_account": "BA0000QDWEEAFB", "mandate_request": "MRQ123", "organisation": "OR123" }, "actions": [ { "type": "confirm_payer_details", "required": true, "completes_actions": [], "requires_actions": [ "collect_customer_details", "collect_bank_account" ], "status": "completed" }, ..., ], "resources": { ..., } } } } ``` Note that: - The `confirm_payer_details` action is now `completed`, and the billing request is in `ready_to_fulfil` state. We can now move on to fulfilling this Billing Request. #### Action: fulfil Once the billing request is in `ready_to_fulfil` state we can complete setting up this mandate by POST'ing to the [billing request fulfil](/docs/api-reference/billing-request#fulfil-a-billing-request) endpoint. ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->fulfil("BR123"); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.fulfil("BR123") ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.fulfil("BR123") ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); client.billingRequests().fulfil("BR123").execute(); ``` ```javascript JavaScript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const resp = await client.billingRequests.fulfil("BR123"); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequests.FulfilAsync("BR123"); ``` ```http HTTP POST https://api.gocardless.com/billing_requests/BRQ123/actions/fulfil HTTP/1.1 ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestFulfilParams := gocardless.BillingRequestFulfilParams{} billingRequest, err := client.BillingRequests.Fulfil(context, "BR123", billingRequestFulfilParams) ``` As with all action endpoints, the response is the Billing Request. What we get back is: ```json { "billing_requests": { "id": "BRQ123", "status": "fulfilled", "mandate_request": { "currency": "USD", "scheme": "ach", "authorisation_source": "teleohone" }, "links": { "customer": "CU00016WDAM7BS", "customer_billing_detail": "CBD000010P52VRF", "customer_bank_account": "BA123", "organisation": "OR123", "mandate_request": "MRQ123" }, "actions": [], "resources": { ..., } } } } ``` #### Done! The mandate has now been created and is ready to create payments against. The Billing Request is `fulfilled`, and cannot be modified. ### Core Endpoints > **Info:** > The endpoints in this section are legacy API endpoints and do not support GoCardless' newest > features. We recommend using the [Billing Requests API](#billing-requests-api) instead. #### Create a customer Before you create a mandate using the core endpoints, you will need to create a customer and create a bank account for that customer. We will start by creating a customer. Use the [Create a customer](/docs/api-reference/customer#create-a-customer) endpoint. ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->customers()->create([ "params" => ["email" => "user@example.com", "given_name" => "Frank", "family_name" => "Osborne", "address_line1" => "27 Acer Road", "address_link2" => "Apt 2", "city" => "Los Angeles", "postal_code" => "90213", "country_code" => "US", "region" => "CA"] ]); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.customers.create(params={ "email": "user@example.com", "given_name": "Frank", "family_name": "Osborne", "address_line1": "27 Acer Road", "address_line2": "Apt 2", "city": "Los Angeles", "postal_code": "90213", "country_code": "US", "region": "CA" }) ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.customers.create( params: { email: "user@example.com", given_name: "Frank", family_name: "Osborne", address_line1: "27 Acer Road", address_line2: "Apt 2", city: "Los Angeles", postal_code: "90213", country_code: "US", region: "CA" } ) ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); Customer customer = client.customers().create() .withEmail("user@example.com") .withGivenName("Frank") .withFamilyName("Osborne") .withAddressLine1("27 Acer Road") .withAddressLine2("Apt 2") .withCity("Los Angeles") .withPostalCode("90213") .withCountryCode("US") .withRegion("CA") .execute(); ``` ```javascript JavaScript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const customer = await client.customers.create({ email: "user@example.com", given_name: "Frank", family_name: "Osborne", address_line1: "27 Acer Road", address_line2: "Apt 2", city: "Los Angeles", postal_code: "90213", country_code: "US", region: "CA", }); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var customerRequest = new GoCardless.Services.CustomerCreateRequest() { Email = "user@example.com", GivenName = "Frank", FamilyName = "Osborne", AddressLine1 = "27 Acer Road", AddressLine2 = "Apt 2", City = "Los Angeles", PostalCode = " 90213", CountryCode = "US", Region = "CA", }; var customerResponse = await gocardless.Customers.CreateAsync(customerRequest); GoCardless.Resources.Customer customer = customerResponse.Customer; ``` ```http HTTP POST https://api.gocardless.com/customers HTTP/1.1 { "customers": { "email": "user@example.com", "given_name": "Frank", "family_name": "Osborne", "address_line1": "27 Acer Road", "address_line2": "Apt 2", "city": "Los Angeles", "postal_code": "90213", "country_code": "US", "region": "CA" } } ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } customerCreateParams := gocardless.CustomerCreateParams{ AddressLine1: "27 Acer Road", AddressLine2: "Apt 2", City: "Los Angeles", PostalCode: "90213", CountryCode: "US", Region: "CA", Email: "user@example.com", GivenName: "Frank", FamilyName: "Osborne", } customer, err := client.Customers.Create(context, customerCreateParams) ``` This returns a customer that will look something like this: ```json { "customers": { "id": "CU0000QGB3Q04D", "created_at": "2022-12-14T10:44:07.558Z", "email": "user@example.com", "given_name": "Frank", "family_name": "Osborne", "company_name": null, "address_line1": "27 Acer Road", "address_line2": "Apt 2", "address_line3": null, "city": "Los Angeles", "region": "CA", "postal_code": "90213", "country_code": "US", "language": "en", "swedish_identity_number": null, "danish_identity_number": null, "phone_number": null, "metadata": {} } } ``` We will be using the id of the customer in the next step to create the customer bank account. #### Create a customer bank account Create a new customer bank account, linking the customer `id` from the previous step. Use the [Create a customer bank account](/docs/api-reference/customer-bank-account#create-a-customer-bank-account) endpoint. ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->customerBankAccounts()->create([ "params" => ["account_number" => "2715500356", "branch_code" => "026073150", "account_holder_name" => "Frank Osborne", "currency" => "USD", "country_code" => "US", "account_type" => "checking", "links" => ["customer" => "CU123"]] ]); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.customer_bank_accounts.create(params={ "account_number": "2715500356", "branch_code": "026073150", "account_holder_name": "Frank Osborne", "country_code": "US", "currency": "USD", "account_type": "checking", "links": { "customer": "CU123" } }) ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.customer_bank_accounts.create( params: { account_holder_name: "Frank Osborne", account_number: "2715500356", branch_code: "026073150", country_code: "US", currency: "USD", account_type: "checking", links: { customer: "CU123" } } ) ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); CustomerBankAccount customerBankAccount = client.customerBankAccounts().create() .withAccountNumber("2715500356") .withBranchCode("026073150") .withAccountHolderName("Frank Osborne") .withCurrency("USD") .withCountryCode("US") .withAccountType("checking") .withLinksCustomer("CU123") .execute(); ``` ```javascript JavaScript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const customerBankAccount = await client.customerBankAccounts.create({ account_number: "2715500356", branch_code: "026073150", account_holder_name: "Frank Osborne", country_code: "US", currency: "USD", account_type: "checking", links: { customer: "CU123", }, }); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var customerBankAccountRequest = new GoCardless.Services.CustomerBankAccountCreateRequest() { AccountHolderName = "Frank Osborne", AccountNumber = "2715500356", BranchCode = "026073150", CountryCode = "US", Currency = "USD", AccountType = "checking" Links = new GoCardless.Services.CustomerBankAccountCreateRequest.CustomerBankAccountLinks() { Customer = "CU0123" } }; var customerBankAccountResponse = await gocardless.CustomerBankAccounts.CreateAsync(customerBankAccountRequest); GoCardless.Resources.CustomerBankAccount customerBankAccount = customerBankAccountResponse.CustomerBankAccount; ``` ```http HTTP POST https://api.gocardless.com/customer_bank_accounts HTTP/1.1 { "customer_bank_accounts": { "account_number": "2715500356", "branch_code": "026073150", "account_holder_name": "Frank Osborne", "currency": "USD", "country_code": "US", "account_type": "checking", "links": { "customer": "CU123" } } } ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } customerBankAccountCreateParams := gocardless.CustomerBankAccountCreateParams{ AccountNumber: "2715500356", BranchCode: "026073150", AccountHolderName: "Frank Osborne", CountryCode: "US", Currency: "USD", AccountType: "checking", Links: gocardless.CustomerBankAccountCreateParamsLinks{ Customer: "CU123", }, } customerBankAccount, err := client.CustomerBankAccounts.Create(context, customerBankAccountCreateParams) ``` This will return a customer bank account that will look like this: ```json { "customer_bank_accounts": { "id": "BA123", "created_at": "2014-05-08T17:01:06.000Z", "account_number_ending": "56", "account_holder_name": "FRANK OSBORNE", "account_type": "checking", "bank_name": "Community Federal Savings Bank", "currency": "USD", "country_code": "US", "metadata": {}, "enabled": true, "links": { "customer": "CU123" } } } ``` We will be using the `id` of the `customer_bank_account` in the next step to create a mandate. #### Create an offline mandate via Mandate API Create a Mandate request linking the `customer_bank_account` in the request. For ACH specific mandates, you can provide the `authorisation_source` field to create an offline mandate. The `authorisation_source` field specifies the way in which the payer gave authorisation to the merchant. This is sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This field takes values of either `telephone`, `paper` or `web`. Use the [Create a mandate](/docs/api-reference/mandate#create-a-mandate) endpoint: ```php PHP $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->mandates()->create([ "params" => ["scheme" => "ach", "authorisation_source" => "telephone", "links" => ["customer_bank_account" => "BA123","creditor" => "CR123"]] ]); ``` ```python Python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.mandates.create(params={ "scheme": "ach", "links": { "customer_bank_account": "BA123", "creditor": "CR123" }, "authorisation_source": "telephone" }) ``` ```ruby Ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.mandates.create( params: { scheme: "ach", links: { customer_bank_account: "BA123", creditor: "CR123" }, authorisation_source: "telephone" } ) ``` ```java Java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); Mandate mandate = client.mandates().create() .withScheme("ach") .withLinksCustomerBankAccount("BA123") .withLinksCreditor("CR123") .withAuthorisationSource("telephone") .execute(); ``` ```javascript JavaScript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const mandate = await client.mandates.create({ scheme: "ach", links: { customer_bank_account: "BA123", creditor: "CR123", }, authorisation_source: "telephone", }); ``` ```csharp .net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var mandateRequest = new GoCardless.Services.MandateCreateRequest() { Links = new GoCardless.Services.MandateCreateRequest.MandateLinks() { CustomerBankAccount = "BA0123", Creditor = "CR0123" }, Scheme = "ach", AuthorisationSource = "telephone" }; var mandateResponse = await gocardless.Mandates.CreateAsync(mandateRequest); GoCardless.Resources.Mandate mandate = mandateResponse.Mandate; ``` ```http HTTP POST https://api.gocardless.com/mandates HTTP/1.1 { "mandates": { "scheme": "ach", "links": { "customer_bank_account": "BA123", "creditor": "CR123" }, "authorisation_source": "telephone" } } ``` ```go Go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } mandateCreateParams := gocardless.MandateCreateParams{ Scheme: "ach", AuthorisationSource: "telephone", Links: gocardless.MandateCreateParamsLinks{ CustomerBankAccount: "BA123", Creditor: "CR123", } } mandate, err := clinet.Mandates().Create(context, mandateCreateParams) ``` You'll receive a full Mandate resource back. It will look like this, some detail omitted: ```json { "mandates": { "id": "MD123", "created_at": "2014-05-08T17:01:06.000Z", "reference": "REF-123", "status": "pending_submission", "scheme": "ach", "next_possible_charge_date": "2014-11-10", "metadata": { "contract": "ABCD1234" }, "links": { "customer_bank_account": "BA123", "creditor": "CR123", "customer": "CU123" }, "authorisation_source": "telephone" } } ``` You can now take payments from this mandate using the [Create a payment](/docs/api-reference/payment#create-a-payment) API. ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates online via the hosted Billing Requests flow. #### [ACH and PAD Consent Types](/docs/collect-payments/scheme-guidance/ach-and-pad-consent-types) Specify the authorization type when creating ACH or PAD mandates. #### [Mandate Events](/docs/collect-payments/events-and-webhooks/mandate-events) Handle webhooks as offline mandates move through their lifecycle. #### [Billing Requests API Reference](/docs/api-reference/billing-request) Full reference for the Billing Requests API, including offline mandate fields. ## One-off Direct Debit URL: https://docs.gocardless.com/docs/collect-payments/one-off-payments/one-off-direct-debit > Create a one-off payment against an existing mandate. # One-off Direct Debit One-off Direct Debits allow you to collect fixed or variable amounts from your customers on a flexible schedule. The customer sets up a Direct Debit mandate once; after that, you can collect payments of any amount at any time without requiring re-authorisation. **Best for:** Usage-based billing, professional services with variable charges, invoice payments. ## One-off Direct Debit vs Pay By Bank | | One-off via Direct Debit | Pay By Bank | | -------------------------- | ------------------------------------------- | -------------------------------- | | Mandate required | Yes | No | | Customer authorisation | Once (mandate setup) | Per payment | | Confirmation speed | 2-5 business days | Minutes | | Re-use for future payments | Yes, collect again without re-authorisation | No, new authorisation each time | | Protection | Scheme-specific | None | | Customer experience | One-time setup, then hands-off | The bank app redirects each time | For time-sensitive payments, consider [Pay By Bank](/docs/collect-payments/one-off-payments/pay-by-bank), which confirms within seconds. If you need immediate confirmation for the first payment but also want a mandate for future charges, use [Instant Payment + DD Setup](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) instead. ## How it works 1. The customer sets up a mandate via your chosen integration 2. You create a payment against the mandate via the API 3. GoCardless collects the payment (typically 2-5 business days) 4. You receive a webhook confirming the payment status 5. Funds are included in your next payout **Key differences from recurring payments:** You control when and how much to charge. There's no automatic schedule; you create each payment individually via the API. ## Step-by-step guide ### Create a billing request ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python import os import gocardless_pro client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'mandate_request': { 'scheme': 'bacs', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { mandate_request: { scheme: 'bacs' } } ) ``` ```java import com.gocardless.GoCardlessClient; GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```net using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main import ( "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "pending", "mandate_request": { "currency": "GBP", "scheme": "bacs" } } } ``` ### Confirm the mandate After creating the Billing Request, direct the customer to authorise the mandate. How you do this depends on your integration type: - Hosted Pages — Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages). - Custom API — Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). ### Handle the outcome Listen for webhooks to confirm the payment status: | Event | Meaning | | ------------------------- | -------------------------------- | | billing_request_fulfilled | Customer authorised the mandate | | mandates_created | Mandate created and ready to use | | mandates_active | Mandate active | ### Collect a payment Retrieve the mandate ID from the fulfilled billing request: ```http curl https://api.gocardless.com/billing_requests/BRQ000123 \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->get('BRQ000123'); $mandateId = $response->mandate_request->links->mandate; ``` ```python import os import gocardless_pro client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```java import com.gocardless.GoCardlessClient; GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests() .get("BRQ000123") .execute(); String mandateId = billingRequest.getMandateRequest().getLinks().getMandate(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const billingRequest = await client.billingRequests.find("BRQ000123"); const mandateId = billingRequest.mandate_request.links.mandate; ``` ```net using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var billingRequest = await client.BillingRequests.GetAsync("BRQ000123"); var mandateId = billingRequest.MandateRequest.Links.Mandate; ``` ```go package main import ( "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } billingRequest, err := client.BillingRequests.Get(context.TODO(), "BRQ000123") if err != nil { panic(err) } mandateId := billingRequest.MandateRequest.Links.Mandate fmt.Println(mandateId) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "fulfilled", "mandate_request": { "scheme": "bacs", "links": { "mandate": "MD123" } } } } ``` **Then collect whenever you need to:** ```http curl -X POST https://api.gocardless.com/payments \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "payments": { "amount": 5000, "currency": "GBP", "description": "Order #1234", "links": { "mandate": "MD123" } } }' ``` ```php $response = $client->payments()->create([ 'params' => [ 'amount' => 5000, 'currency' => 'GBP', 'description' => 'Order #1234', 'links' => [ 'mandate' => 'MD123', ], ], ]); ``` ```python response = client.payments.create( params={ 'amount': 5000, 'currency': 'GBP', 'description': 'Order #1234', 'links': { 'mandate': 'MD123', }, } ) ``` ```ruby response = client.payments.create( params: { amount: 5000, currency: 'GBP', description: 'Order #1234', links: { mandate: 'MD123' } } ) ``` ```java Payment payment = client.payments() .create() .withAmount(5000) .withCurrency("GBP") .withDescription("Order #1234") .withLinksMandate("MD123") .execute(); ``` ```javascript const payment = await client.payments.create({ amount: 5000, currency: "GBP", description: "Order #1234", links: { mandate: "MD123", }, }); ``` ```net var payment = await client.Payments.CreateAsync( new PaymentCreateRequest { Amount = 5000, Currency = "GBP", Description = "Order #1234", Links = new PaymentCreateRequest.PaymentLinks { Mandate = "MD123" } } ); ``` ```go params := gocardless.PaymentCreateParams{ Amount: 5000, Currency: "GBP", Description: "Order #1234", Links: gocardless.PaymentCreateParamsLinks{ Mandate: "MD123", }, } payment, err := client.Payments.Create(context.TODO(), params) ``` ## What's next? #### [Pay By Bank](/docs/collect-payments/one-off-payments/pay-by-bank) Instant bank payments that confirm within seconds — no mandate required. #### [Recurring Payments](/docs/collect-payments/recurring-payments/subscriptions) Set up automatic subscription schedules against an active mandate. #### [Instant Payment + DD Setup](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) Collect an instant first payment while setting up a mandate for future charges. #### [Mandate Events](/docs/collect-payments/events-and-webhooks/mandate-events) Understand the webhooks fired during the mandate and payment lifecycle. ## Pay By Bank URL: https://docs.gocardless.com/docs/collect-payments/one-off-payments/pay-by-bank > Collect a one-off payment directly from your customer # Pay By Bank Pay By Bank lets you collect a one-off payment directly from your customer's bank account with confirmation within minutes. Unlike Direct Debit, there's no mandate — the customer must authorise each payment individually via their banking app. **Availability:** GBP (Faster Payments), EUR (SEPA Instant). You can also use [Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) for a no-code approach — Drop-in Flow does not support Pay By Bank. **Best for:** E-commerce checkouts, one-time purchases, time-sensitive payments, high-value transactions where immediate confirmation is needed, replacing card payments to reduce fees and eliminate chargebacks. ## Pay By Bank vs One-off Direct Debit | | Pay By Bank | One-off via Direct Debit | | -------------------------- | -------------------------------- | ------------------------------------------- | | Mandate required | No | Yes | | Customer authorisation | Per payment | Once (mandate setup) | | Confirmation speed | Minutes | 2-5 business days | | Re-use for future payments | No, new authorisation each time | Yes, collect again without re-authorisation | | Protection | None | Scheme-specific | | Customer experience | The bank app redirects each time | One-time setup, then hands-off | If you expect to charge the customer more than once, a [Direct Debit mandate](/docs/collect-payments/setting-up-mandates) is usually better — the customer authorises once and you can collect future payments without requiring them to open their banking app again. If you need immediate confirmation for the first payment but also want a mandate for future charges, use [Instant Payment + DD Setup](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) instead. ## How it works 1. You create a Billing Request with a payment_request — no mandate_request 2. The customer authorises the payment via your chosen integration 3. The customer is redirected to their banking app to approve 4. Payment is confirmed within seconds 5. You receive a billing_requests.fulfilled webhook — payment is processing 6. You receive a payments.confirmed webhook — payment is settled 7. Funds arrive in your account (typically next business day) ## Step-by-step guide ### Create a Billing Request ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "payment_request": { "description": "Order #9012", "amount": 12000, "currency": "GBP", "scheme": "faster_payments" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'payment_request' => [ 'description' => 'Order #9012', 'amount' => 12000, 'currency' => 'GBP', 'scheme' => 'faster_payments', ], ], ]); ``` ```python import os import gocardless_pro client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'payment_request': { 'description': 'Order #9012', 'amount': 12000, 'currency': 'GBP', 'scheme': 'faster_payments', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { payment_request: { description: 'Order #9012', amount: 12000, currency: 'GBP', scheme: 'faster_payments' } } ) ``` ```java import com.gocardless.GoCardlessClient; GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withPaymentRequestDescription("Order #9012") .withPaymentRequestAmount(12000) .withPaymentRequestCurrency("GBP") .withPaymentRequestScheme("faster_payments") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ payment_request: { description: "Order #9012", amount: 12000, currency: "GBP", scheme: "faster_payments", }, }); ``` ```net using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { PaymentRequest = new BillingRequestCreateRequest.BillingRequestPaymentRequest { Description = "Order #9012", Amount = 12000, Currency = "GBP", Scheme = "faster_payments" } } ); ``` ```go package main import ( "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ PaymentRequest: &gocardless.BillingRequestCreateParamsPaymentRequest{ Description: "Order #9012", Amount: 12000, Currency: "GBP", Scheme: "faster_payments", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ0000302", "status": "pending", "payment_request": { "amount": 12000, "currency": "GBP", "scheme": "faster_payments" }, "actions": [ { "type": "collect_customer_details", "required": true, "completed": false }, { "type": "select_institution", "required": true, "completed": false }, { "type": "bank_authorisation", "required": true, "completed": false } ] } } ``` ### Confirm the payment After creating the Billing Request, direct the customer to authorise the payment. How you do this depends on your integration type: - Hosted Pages — Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages). - Custom API — Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). > **Warning:** > Don't use the redirect to confirm the outcome. Always use webhooks. ### Handle the outcome Listen for webhooks to confirm the payment status: | Event | Meaning | | ------------------------- | ----------------------------------------------- | | billing_request_fulfilled | Customer authorised, payment is being processed | | payment_confirmed | Payment confirmed and settled | | payment_failed | Payment failed (e.g., insufficient funds) | ## What's next? #### [Billing Request Events](/docs/collect-payments/events-and-webhooks/billing-request-events) Understand the full event lifecycle for Pay By Bank payments. #### [One-off Direct Debit](/docs/collect-payments/one-off-payments/one-off-direct-debit) Set up a mandate so future payments don't require re-authorisation. #### [Instant Payment + DD Setup](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate) Combine instant first payment with mandate setup for future charges. #### [Retain Customers with Fallbacks](/docs/optimise/retain-customers-with-fallbacks) Offer a fallback payment method when bank authorisation fails. ## PayTo Agreements and Payments URL: https://docs.gocardless.com/docs/collect-payments/recurring-payments/payto > Set up PayTo mandates and real-time payments in Australia. # PayTo Agreements and Payments PayTo is a real-time payment scheme for Australian bank accounts. GoCardless supports two use cases: setting up an open mandate with your customer, and taking one-off real-time payments. > **Info:** > PayTo uses the term "agreement" for the contract between you and your customer. This maps to a > "mandate" in the GoCardless API. The two terms are synonymous — customers will see "agreement" in > the payment flow. ## Step 1: Create a Billing Request Use the `mandate_request` field when creating a Billing Request to set up a PayTo mandate. The following requirements must be met: - `scheme` must be `pay_to` - `purpose_code` is required - `description` is required - `constraints` is optional ### Purpose code The `purpose_code` attribute specifies the high-level purpose of the mandate. Accepted values are: `mortgage`, `utility`, `loan`, `dependant_support`, `gambling`, `retail`, `salary`, `personal`, `government`, `pension`, `tax`, and `other`. See the full list of supported values in [Billing Request Purpose Codes](/docs/collect-payments/scheme-guidance/billing-request-purpose-codes). ### Constraints Constraints specify the limits on recurring payments, allowing you to collect payments without requiring the payer to re-consent each time — provided payments fall within the agreed constraints. | Parameter | Description | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `start_date` | Date from which the consent is valid. Must not be in the past; the payer must have enough time to complete the flow before this date. | | `end_date` | Date after which payments cannot be collected. Must not be in the past or before `start_date`. | | `max_amount_per_payment` | Maximum amount that can be charged per payment. | | `periodic_limits[].period` | Repeating time frame: `year`, `month`, `week`, or `day`. | | `periodic_limits[].max_payments` | Maximum number of payments that can be taken within the period. | ### Example request ```http POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "purpose_code": "mortgage", "mandate_request": { "currency": "AUD", "scheme": "pay_to", "constraints": { "start_date": "2030-06-27", "end_date": "2020-12-30", "max_amount_per_payment": 100, "periodic_limits": [{ "period": "month", "max_payments": 2 }] } } } } ``` You'll receive a full Billing Request object in response: ```json { "billing_requests": { "id": "BR123", "status": "pending", "mandate_request": { "currency": "AUD", "scheme": "pay_to", "constraints": { "start_date": "2030-06-27", "end_date": "2020-12-30", "max_amount_per_payment": 100, "periodic_limits": [ { "period": "month", "max_payments": 2 } ] } }, "payment_request": null, "metadata": null, "links": { "customer": "CU123", "customer_billing_detail": "CBD123", "creditor": "CR123", "organisation": "OR123", "mandate_request": "MRQ123" }, "purpose_code": "mortgage", "creditor_name": "Hotel Park Grand", "actions": [ { "type": "collect_customer_details", "required": true, "status": "pending" }, { "type": "collect_bank_account", "required": true, "status": "pending" }, { "type": "bank_authorisation", "required": true, "status": "pending" } ] } } ``` ## Step 2: Create a Billing Request Flow Create a Billing Request Flow to generate a hosted checkout link for your customer. For PayTo, always include an `exit_uri`. > **Warning:** > Some banks do not yet support PayTo. If a customer's bank is unsupported, they will be redirected > to the `exit_uri` rather than reaching a dead end. We recommend sending them back to your checkout > page so they can choose an alternative payment method. ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequestFlows()->create([ "params" => [ "redirect_uri" => "https://my-company.com/landing", "exit_uri" => "https://my-company.com/exit", "links" => [ "billing_request" => "BRQ000010NMDMH2" ] ] ]); ``` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_request_flows.create(params={ "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_request_flows.create( params: { redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create() .withRedirectUri("https://my-company.com/landing") .withExitUri("https://my-company.com/exit") .withLinksBillingRequest("BRQ000010NMDMH2") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequestFlow = await client.billingRequestFlows.create({ redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequestFlows.CreateAsync( new GoCardless.Services.BillingRequestFlowCreateRequest() { RedirectUri = "https://my-company.com/landing", ExitUri = "https://my-company.com/exit", Links = new GoCardless.Services.BillingRequestFlowCreateRequest.BillingRequestFlowLinks { BillingRequest = "BRQ000010NMDMH2", }, } ); GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow; ``` ```http POST https://api.gocardless.com/billing_request_flows HTTP/1.1 { "billing_request_flows": { "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here"; opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(accessToken, opts) billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams{} billingRequestFlowCreateParams.RedirectUri = "https://my-company.com/landing" billingRequestFlowCreateParams.ExitUri = "https://my-company.com/exit" billingRequestFlowCreateParams.Links.BillingRequest = "BRQ000010NMDMH2" billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams) ``` ```json { "billing_request_flows": { "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=", "lock_customer_details": false, "lock_bank_account": false, "auto_fulfil": true, "created_at": "2021-03-30T16:23:10.679Z", "expires_at": "2021-04-06T16:23:10.679Z", "redirect_uri": "https://my-company.com/completed", "links": { "billing_request": "BRQ123" } } } ``` Send the `authorisation_url` from the response to your customer via a button, email, SMS, or any other channel. ## Existing customers and locking **Skip steps for existing customers** — If you already have a customer on record, pass their ID in `links.customer` on the Billing Request to skip the customer details step. Similarly, pass `links.customer_bank_account` to skip the bank account step. The customer can still edit these details unless they are locked. **Lock details** — Set `lock_customer_details` or `lock_bank_account` to `true` on the Billing Request Flow to prevent the customer from changing those details. When both are locked, the customer skips directly to the confirmation step. **Lock scheme and currency** — For mandate-only requests, you can set `lock_currency` to `true` on the Billing Request Flow. This prevents the customer from changing the scheme or currency, ensuring the mandate is always set up in PayTo. ## What the customer will see ### Collect customer details The customer provides their personal details. This step is skipped if customer details already exist or have been locked. ![Collect customer details screen](/images/docs/collect-payments/recurring-payments/payto/screenshot_2024-01-11_at_08.18.24.png) ### Collect bank details The customer provides their PayID or bank details. This step is skipped if bank details already exist or have been locked. ![Collect bank details screen](/images/docs/collect-payments/recurring-payments/payto/screenshot_2024-01-11_at_08.32.02.png) ### Bank authorisation The customer is prompted to complete the authorisation in their banking app. Depending on their bank, they may also receive a push notification or SMS. ![Bank authorisation screen](/images/docs/collect-payments/recurring-payments/payto/screenshot_2024-01-11_at_08.54.56.png) ### Confirmation Once authorisation is complete, a confirmation screen is shown. All required actions are fulfilled and the Billing Request is complete. ![Confirmation screen](/images/docs/collect-payments/recurring-payments/payto/screenshot_2024-01-11_at_08.53.18.png) ## What's next? #### [Billing Request Purpose Codes](/docs/collect-payments/scheme-guidance/billing-request-purpose-codes) Full list of supported purpose codes for PayTo and other schemes. #### [Test Bank Details](/docs/developer-resources/test-bank-details) Use sandbox bank details to test your PayTo integration. #### [Billing Request Events](/docs/collect-payments/events-and-webhooks/billing-request-events) Understand the webhook events fired during the PayTo agreement lifecycle. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Learn how to set up Direct Debit mandates using Billing Requests. ## Recurring Payments URL: https://docs.gocardless.com/docs/collect-payments/recurring-payments/subscriptions > Set up subscription payments with GoCardless. # Subscriptions ## What are Subscriptions? Automatically collect fixed amounts at regular intervals. Set up a subscription once, and GoCardless handles collection on schedule. **When to use Subscriptions** - SaaS subscriptions - Membership fees - Content subscriptions - Gym memberships, insurance premiums, and ongoing services ## Comparison between other recurring payment options **Key difference from instalments:** Instalment schedules have a defined end. Subscriptions continue indefinitely until cancelled. | | Subscriptions | Instalments | Variable Recurring Payments | Instant Bank Pay + Direct Debit | | ---------------------- | ---------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------- | | Mandate required | Yes | Yes | Yes (consent) | Yes | | Customer authorisation | Once | Once | Once (with agreed limits and frequency) | Once | | Payment amounts | Fixed (per subscription) | Fixed per instalment, can vary across schedule | Variable within agreed constraints | First payment fixed; subsequent payments flexible | | Payment schedule | Merchant-defined recurring (weekly, monthly, yearly) | Merchant-defined schedule with a defined end | Flexible - merchant triggers payments as needed | Flexible after first payment | | Confirmation speed | 2-x business days | 2-x business days | Seconds | First payment: minutes; subsequent: 2-x business days | | Chargeback risk | Yes | Yes | None | First payment: none; subsequent: yes | | Missed payment retries | Yes (with Success+) | Yes (with Success+) | Yes | Subsequent payments: yes | | Best for | SaaS, memberships, gym fees, insurance | Payment plans, tuition, professional services | Usage-based regulated billing and utilities, financial services, government services | Subscription services needing immediate, initial payment | | Availability | All schemes | All schemes | GBP only | GBP and EUR | **Need to change the amount?** If the amount varies between cycles, use one-off payments instead and control each charge individually. Alternatively, you can cancel and recreate a subscription with a new amount. **Only taking payments for a defined period? **If the amount doesn't vary and you wish to only take a certain number of payments, use instalments instead. ## How it works 1. The customer sets up a mandate via your chosen integration 2. You create a payment against the mandate via the API 3. GoCardless collects the payment (typically 2-5 business days) 4. You receive a webhook confirming the payment status 5. Funds are included in your next payout **Frequency options:** Weekly, monthly, yearly, or custom intervals. ## Step-by-step guide ### Create a billing request ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "mandate_request": { "scheme": "bacs" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'mandate_request' => [ 'scheme' => 'bacs', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'mandate_request': { 'scheme': 'bacs', } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { mandate_request: { scheme: 'bacs' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withMandateRequestScheme("bacs") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ mandate_request: { scheme: "bacs", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "pending", "mandate_request": { "currency": "GBP", "scheme": "bacs" } } } ``` ### Confirm the mandate After creating the Billing Request, direct the customer to authorise the mandate. How you do this depends on your integration type: - Hosted Pages - Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Payment Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages). - Custom API - Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). ### Handle the outcome Once fulfilled, retrieve both mandate ID and payment ID from the billing request: ```http curl https://api.gocardless.com/billing_requests/BRQ000123 \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->get('BRQ000123'); $mandateId = $response->mandate_request->links->mandate; ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests() .get("BRQ000123") .execute(); String mandateId = billingRequest.getMandateRequest().getLinks().getMandate(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const billingRequest = await client.billingRequests.find("BRQ000123"); const mandateId = billingRequest.mandate_request.links.mandate; ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var billingRequest = await client.BillingRequests.GetAsync("BRQ000123"); var mandateId = billingRequest.MandateRequest.Links.Mandate; ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } billingRequest, err := client.BillingRequests.Get(context.TODO(), "BRQ000123") if err != nil { panic(err) } mandateId := billingRequest.MandateRequest.Links.Mandate fmt.Println(mandateId) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "fulfilled", "mandate_request": { "scheme": "bacs", "links": { "mandate": "MD123" } } } } ``` Listen for webhooks to confirm the payment status: | Event | Meaning | | ------------------------- | -------------------------------- | | billing_request_fulfilled | Customer authorised the mandate | | mandates_created | Mandate created and ready to use | | mandates_active | Mandate active | ### Handle the subscription Once the mandate is active, set up recurring payments against it: ```http curl -X POST https://api.gocardless.com/subscriptions \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "subscriptions": { "amount": 5000, "currency": "GBP", "name": "Monthly subscription", "interval_unit": "monthly", "interval": 1, "start_date": "2024-11-01", "links": { "mandate": "MD123" } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->subscriptions()->create([ 'params' => [ 'amount' => 2500, 'currency' => 'GBP', 'name' => 'Monthly Magazine', 'interval_unit' => 'monthly', 'interval' => 1, 'day_of_month' => 1, 'start_date' => '2024-11-01', 'links' => [ 'mandate' => 'MD123', ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.subscriptions.create( params={ 'amount': 2500, 'currency': 'GBP', 'name': 'Monthly Magazine', 'interval_unit': 'monthly', 'interval': 1, 'day_of_month': 1, 'start_date': '2024-11-01', 'links': { 'mandate': 'MD123', }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.subscriptions.create( params: { amount: 2500, currency: 'GBP', name: 'Monthly Magazine', interval_unit: 'monthly', interval: 1, day_of_month: 1, start_date: '2024-11-01', links: { mandate: 'MD123' } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); Subscription subscription = client.subscriptions() .create() .withAmount(2500) .withCurrency("GBP") .withName("Monthly Magazine") .withIntervalUnit(Subscription.IntervalUnit.MONTHLY) .withInterval(1) .withDayOfMonth(1) .withStartDate("2024-11-01") .withLinksMandate("MD123") .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const subscription = await client.subscriptions.create({ amount: 2500, currency: "GBP", name: "Monthly Magazine", interval_unit: "monthly", interval: 1, day_of_month: 1, start_date: "2024-11-01", links: { mandate: "MD123", }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var subscription = await client.Subscriptions.CreateAsync( new SubscriptionCreateRequest { Amount = 2500, Currency = "GBP", Name = "Monthly Magazine", IntervalUnit = SubscriptionCreateRequest.SubscriptionIntervalUnit.Monthly, Interval = 1, DayOfMonth = 1, StartDate = "2024-11-01", Links = new SubscriptionCreateRequest.SubscriptionLinks { Mandate = "MD123" } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } params := gocardless.SubscriptionCreateParams{ Amount: 2500, Currency: "GBP", Name: "Monthly Magazine", IntervalUnit: "monthly", Interval: 1, DayOfMonth: 1, StartDate: "2024-11-01", Links: gocardless.SubscriptionCreateParamsLinks{ Mandate: "MD123", }, } subscription, err := client.Subscriptions.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(subscription) } ``` **Response:** ```json { "subscriptions": { "id": "SB123", "status": "active", "amount": 2500, "currency": "GBP", "interval": 1, "interval_unit": "monthly", "start_date": "2024-11-01", "upcoming_payments": [ { "charge_date": "2024-11-01", "amount": 2500 }, { "charge_date": "2024-12-01", "amount": 2500 } ], "links": { "mandate": "MD123" } } } ``` ### Manage the subscription Listen for webhooks to confirm the mandate status and notifications about future payments: | **Event** | **Meaning** | | ----------------------------- | ----------------------------------------- | | subscriptions_created | Subscription set up successfully | | subscriptions_payment_created | A scheduled payment was created | | payments_confirmed | Recurring payment collected successfully | | payments_failed | Recurring payment failed | | subscriptions_finished | All payments collected (if count was set) | | subscriptions_cancelled | Subscription cancelled | You can also cancel the subscription: ```http curl -X POST https://api.gocardless.com/subscriptions/SB123/actions/cancel \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php $response = $client->subscriptions()->cancel('SB123'); ``` ```python response = client.subscriptions.cancel('SB123') ``` ```ruby response = client.subscriptions.cancel('SB123') ``` ```java Subscription subscription = client.subscriptions() .cancel("SB123") .execute(); ``` ```javascript const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); ``` ```cs var subscription = await client.Subscriptions.CancelAsync("SB123"); ``` ```go subscription, err := client.Subscriptions.Cancel(context.TODO(), "SB123", gocardless.SubscriptionCancelParams{}) ``` Or pause the subscription: ```http curl -X POST https://api.gocardless.com/subscriptions/SB123/actions/pause \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "data": { "pause_cycles": 3 } }' ``` ```php $response = $client->subscriptions()->pause('SB123', [ 'params' => [ 'pause_cycles' => 3, ], ]); ``` ```python response = client.subscriptions.pause( 'SB123', params={ 'pause_cycles': 3, } ) ``` ```ruby response = client.subscriptions.pause( 'SB123', params: { pause_cycles: 3 } ) ``` ```java Subscription subscription = client.subscriptions() .pause("SB123") .withPauseCycles(3) .execute(); ``` ```javascript const subscription = await client.subscriptions.pause("SB123", { pause_cycles: 3, }); ``` ```cs var subscription = await client.Subscriptions.PauseAsync( "SB123", new SubscriptionPauseRequest { PauseCycles = 3 } ); ``` ```go params := gocardless.SubscriptionPauseParams{ PauseCycles: 3, } subscription, err := client.Subscriptions.Pause(context.TODO(), "SB123", params) ``` And resume the subscription: ```http curl -X POST https://api.gocardless.com/subscriptions/SB123/actions/resume \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php $response = $client->subscriptions()->resume('SB123'); ``` ```python response = client.subscriptions.resume('SB123') ``` ```ruby response = client.subscriptions.resume('SB123') ``` ```java Subscription subscription = client.subscriptions() .resume("SB123") .execute(); ``` ```javascript const subscription = await client.subscriptions.resume("SB123"); ``` ```cs var subscription = await client.Subscriptions.ResumeAsync("SB123"); ``` ```go subscription, err := client.Subscriptions.Resume(context.TODO(), "SB123", gocardless.SubscriptionResumeParams{}) ``` ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates and collect bank account details via the API. #### [Instalment Schedules](/docs/collect-payments/recurring-payments/instalment-schedules) Define a series of payments with individual amounts and charge dates. #### [Subscription Events](/docs/api-reference/events/subscription) Understand the webhook events fired during subscription lifecycle. #### [Success+](/docs/optimise/reduced-failed-payments-with-success-plus) Automatically retry failed subscription payments. ## Scheme Guidance URL: https://docs.gocardless.com/docs/collect-payments/scheme-guidance/ach-and-pad-consent-types > ACH and PAD consent types for Direct Debit schemes. # ACH and PAD Consent Types A consent type is a property submitted as part of the Mandate Request within a Billing Request. Consent types represent the type of authorization the payer is consenting to. Currently, this feature is only available to ACH and PAD schemes. There are three main consent types: | **Consent type** | **Definition** | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | One-off (single for PAD) | A one-off Authorization involves a debit initiated by the merchant based on the payer's authorization for a one-time transfer of funds from the payer's account. | | Recurring | A Recurring Authorization involves setting up processing of payments at regular intervals without any action needed from the payer. This is based on the payer's debit authorization, which is provided to the merchant. | | Standing (sporadic for PAD) | A Standing Authorization allows the payer to pre-approve future transactions that require the merchant's action to initiate. The payer will be informed about how they can authorize these transactions, which may include a phone call, online action, or a text message. | ## Submitting consent types during Billing Request creation Through the submission of consent types, more details about the authorisation can be captured during the creation of the Billing Request, displayed to the payer in their payment flow, and stored for record keeping. Examples: ```achone_off POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "ach", "consent_type": "one_off" }, } } ``` ```achrecurring POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "ach", "consent_type": "recurring" }, } } ``` ```achstanding POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "ach", "consent_type": "standing" }, } } ``` ```padsporadic POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "pad", "consent_type": "sporadic" }, } } ``` ## Request Types When defining a `consent_type` as part of your `mandate_request`, you can also combine this with other request types: `payment_request`, `subscription_request` and `instalment_schedule_request`. When a consent type is combined with a request type, payment details can be shown to the payer. Once the Billing Request is authorised successfully, the mandate and any requested resources are also created. This minimizes the number of API requests that need to be made for resource creation after authorization. In addition, the consent type and associated payment details are propagated to the mandate, and can be viewed on the Mandate PDFs. The use of consent types combined with request types enhances the payer experience and enables the storage of compliant mandate data. Examples: ```json POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "pad", "consent_type": "single" }, "payment_request": { "description": "Registration Fee", "amount": 2000, "scheme": "pad", "currency": "CAD" } } } ``` ```json POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "ach", "consent_type": "recurring" }, "subscription_request": { "amount": 2996, "currency": "USD", "name": "Monthly Magazine", "interval_unit": "monthly", "day_of_month": "3", "count": 10, "payment_reference": "test ref", "metadata": {} } } } ``` When using the `recurring` consent type, it is possible to specify the `payment_method` within the constraints of the `mandate_request`. This is a free text field used to specify information about the payments. The information could include how the payments are calculated (particularly useful for variable payments) or any other useful information. ```json POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "pad", "consent_type": "recurring", "constraints": { "payment_method": "calculated by your consumption of electricity" } } } } ``` ## Combining Multiple Request Types If you use a `recurring` consent type, you can combine a `payment_request` with an `instalment_schedule_request `or a `subscription_request` Examples: ```json POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "pad", "consent_type": "recurring" }, "payment_request": { "description": "Registration Fee", "amount": 2000, "scheme": "pad", "currency": "CAD" }, "subscription_request": { "amount": 5000, "currency": "CAD", "name": "Gold Plan", "interval_unit": "monthly", "day_of_month": "1", "count": 10, "payment_reference": "test ref" } } } ``` ```json POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "payment_request": { "description": "registration fee", "amount": 2000, "scheme": "ach", "currency": "USD" }, "mandate_request": { "scheme": "ach", "consent_type": "recurring" }, "instalment_schedule_request": { "currency": "USD", "instalments": [ { "amount": "10000", "charge_date": "2024-11-25" }, { "amount": "10000", "charge_date": "2024-12-25" } ], "name": "Test instalment", "total_amount": "20000", "metadata": {}, "payment_reference": "test ref", "retry_if_possible": false } } } ``` The table outlines all possible combinations of consent types and request types. | **Consent type** | **Mandate Request** | **One-off payment request** | **Subscription request** | **Instalment schedule request** | | ---------------------------- | ------------------- | --------------------------- | ------------------------ | ------------------------------- | | One-off | ✅ | | ❌ | ❌ | | One-off | ✅ | ✅ | ❌ | ❌ | | Recurring | ✅ | | | | | Recurring and payment method | ✅ | | | | | Recurring | ✅ | | ✅ | ❌ | | Recurring | ✅ | ✅ | ✅ | ❌ | | Recurring | ✅ | | ❌ | ✅ | | Recurring | ✅ | ✅ | ❌ | ✅ | | Standing | ✅ | | ❌ | ❌ | | Standing | ✅ | ✅ | ❌ | ❌ | ## Enforcement After the Billing Request is fulfilled, and the mandate and associated payment resources are created, certain enforcement rules will apply. The enforcement rules apply regardless of how the resources were created (through [Billing Request](/docs/api-reference/billing-request) or [core endpoints](/docs/api-reference)). | **Authorization type** | **Rule** | **Trigger** | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | One-off | can only have one active payment | User tries to create another payment against a one-off authorization that already has an active or fulfilled payment | | One-off | cannot have subscriptions or instalment schedules attached | User tries to create a subscription or instalment schedule against a one-off authorization | | Recurring | can only have one active subscription at a time | User tries to create another subscription against a recurring authorization that already has an active or completed subscription | | Recurring | can only have one instalment schedule at a time | User tries to create another instalment schedule against a recurring authorization that already has an active or finished instalment schedule | | Recurring | can only have a subscription or instalment schedule attached after authorization is created | User tries to create a payment against a recurring authorization that has an active subscription or instalment schedule attached after the authorization is created | | Recurring | cannot have an instalment schedule attached to the authorization when there's already an active or completed subscription | User tries to create an instalment schedule against a recurring authorization that already has an active or completed subscription | | Recurring | cannot have a subscription attached to the authorization when there's already an active or finished instalment schedule | User tries to create a subscription against a recurring authorization that already has an active or finished instalment schedule | | Recurring | cannot attach a subscription and instalment schedule to the same recurring authorization | User tries to create a subscription against a recurring authorization when there is already an active or completed instalment schedule attached, or vice versa. | | Recurring | cannot attach a payment to a recurring authorization if it already has an active or completed subscription / instalment schedule | User tries to create a payment against a recurring authorization that already has an active or completed subscription / instalment schedule | | Standing | Cannot have a subscription or instalment schedule attached | User tries to create a subscription or instalment schedule against a standing authorization | ## What's next? #### [Billing Requests API Reference](/docs/api-reference/billing-request) Full reference for creating Billing Requests with consent types. #### [Purpose Codes](/docs/collect-payments/scheme-guidance/billing-request-purpose-codes) Browse purpose codes for Billing Requests and PayTo. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create ACH and PAD mandates through the Billing Requests API. #### [Subscriptions](/docs/collect-payments/recurring-payments/subscriptions) Use recurring consent type mandates to power subscription payments. ## Variable Recurring Payments URL: https://docs.gocardless.com/docs/collect-payments/recurring-payments/variable-recurring-payments > Set up variable recurring payments. # Variable Recurring Payments ## What are Variable Recurring Payments? Collect real-time recurring payments of varying amounts from a single customer authorisation. The customer consents once via their banking app; you can then collect multiple payments within agreed parameters - no re-authorisations required for each charge. ## When to use Variable Recurring Payments | | **Commercial VRP (cVRP)** | **Sweeping VRP (sVRP)** | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- | | Transfer type | Me-to-Business | Me-to-me | | When to use | Usage-based billing where amounts vary each period (metered services, such as electricity, gas, water and telecoms providers) Local and central government Rail fares Charitable donations | Lending repayments Savings automation and round-ups Automated investment contributions | | Who initiates | Business | Customer's bank | | Payer account types support | Personal | Personal and business | > **Info:** > Variable Recurring Payments feature is only available to approved integrators with the VRP > Sweeping upgrade or VRP Commercial upgrade to use either mechanism respectively. If you're > interested in trying it out - please [contact support](mailto:help@gocardless.com). ## Comparison between other recurring payment options | | Subscriptions | Instalments | Variable Recurring Payments | Instant Bank Pay + Direct Debit | | ---------------------- | ---------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------- | | Mandate required | Yes | Yes | Yes (consent) | Yes | | Customer authorisation | Once | Once | Once (with agreed limits and frequency) | Once | | Payment amounts | Fixed (per subscription) | Fixed per instalment, can vary across schedule | Variable within agreed constraints | First payment fixed; subsequent payments flexible | | Payment schedule | Merchant-defined recurring (weekly, monthly, yearly) | Merchant-defined schedule with a defined end | Flexible - merchant triggers payments as needed | Flexible after first payment | | Confirmation speed | 2-x business days | 2-x business days | Seconds | First payment: minutes; subsequent: 2-x business days | | Chargeback risk | Yes | Yes | None | First payment: none; subsequent: yes | | Missed payment retries | Yes (with Success+) | Yes (with Success+) | Yes | Subsequent payments: yes | | Best for | SaaS, memberships, gym fees, insurance | Payment plans, tuition, professional services | Usage-based regulated billing and utilities, financial services, government services | Subscription services needing immediate, initial payment | | Availability | All schemes | All schemes | GBP only | GBP and EUR | ## How it works 1. The customer authorised a VRP consent via their banking app, setting agreed payment parameters (maximum amount, frequency) 2. You collect payments within those parameters via GoCardless API - no further customer action needed per payment 3. Payment is confirmed within seconds 4. You receive a webhook confirming the payment status 5. Funds arrive same day or next business day ## cVRP: Step-by-step guide ### Create a billing request ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "fallback_enabled": true, "purpose_code": "loan", "payment_context_code": "billing_goods_and_services_in_arrears", "payment_purpose_code": "bank_loan_delayed_draw_funding", "mandate_request": { "scheme": "faster_payments", "constraints": { "start_date": "2024-11-01", "max_amount_per_payment": 50000, "periodic_limits": [{ "period": "month", "max_total_amount": 100000, "alignment": "creation_date" }] } } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'fallback_enabled' => true, 'purpose_code' => 'loan', 'payment_context_code' => 'billing_goods_and_services_in_arrears', 'payment_purpose_code' => 'bank_loan_delayed_draw_funding', 'mandate_request' => [ 'scheme' => 'faster_payments', 'constraints' => [ 'start_date' => '2024-11-01', 'max_amount_per_payment' => 50000, 'periodic_limits' => [ [ 'period' => 'month', 'max_total_amount' => 100000, 'alignment' => 'creation_date', ], ], ], ], ], ]); ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'fallback_enabled': True, 'purpose_code': 'loan', 'payment_context_code': 'billing_goods_and_services_in_arrears', 'payment_purpose_code': 'bank_loan_delayed_draw_funding', 'mandate_request': { 'scheme': 'faster_payments', 'constraints': { 'start_date': '2024-11-01', 'max_amount_per_payment': 50000, 'periodic_limits': [ { 'period': 'month', 'max_total_amount': 100000, 'alignment': 'creation_date', }, ], }, }, } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { fallback_enabled: true, purpose_code: 'loan', payment_context_code: 'billing_goods_and_services_in_arrears', payment_purpose_code: 'bank_loan_delayed_draw_funding', mandate_request: { scheme: 'faster_payments', constraints: { start_date: '2024-11-01', max_amount_per_payment: 50000, periodic_limits: [ { period: 'month', max_total_amount: 100000, alignment: 'creation_date' } ] } } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withFallbackEnabled(true) .withPurposeCode("loan") .withPaymentContextCode("billing_goods_and_services_in_arrears") .withPaymentPurposeCode("bank_loan_delayed_draw_funding") .withMandateRequestScheme("faster_payments") .withMandateRequestConstraintsStartDate("2024-11-01") .withMandateRequestConstraintsMaxAmountPerPayment(50000) .withMandateRequestConstraintsPeriodicLimitsBuilder() .withPeriod("month") .withMaxTotalAmount(100000) .withAlignment("creation_date") .done() .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ fallback_enabled: true, purpose_code: "loan", payment_context_code: "billing_goods_and_services_in_arrears", payment_purpose_code: "bank_loan_delayed_draw_funding", mandate_request: { scheme: "faster_payments", constraints: { start_date: "2024-11-01", max_amount_per_payment: 50000, periodic_limits: [ { period: "month", max_total_amount: 100000, alignment: "creation_date", }, ], }, }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { FallbackEnabled = true, PurposeCode = "loan", PaymentContextCode = "billing_goods_and_services_in_arrears", PaymentPurposeCode = "bank_loan_delayed_draw_funding", MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "faster_payments", Constraints = new BillingRequestCreateRequest.BillingRequestMandateRequestConstraints { StartDate = "2024-11-01", MaxAmountPerPayment = 50000, PeriodicLimits = new List { new BillingRequestCreateRequest.BillingRequestMandateRequestConstraintsPeriodicLimit { Period = "month", MaxTotalAmount = 100000, Alignment = "creation_date" } } } } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } fallbackEnabled := true params := gocardless.BillingRequestCreateParams{ FallbackEnabled: &fallbackEnabled, PurposeCode: "loan", PaymentContextCode: "billing_goods_and_services_in_arrears", PaymentPurposeCode: "bank_loan_delayed_draw_funding", MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "faster_payments", Constraints: &gocardless.BillingRequestCreateParamsMandateRequestConstraints{ StartDate: "2024-11-01", MaxAmountPerPayment: 50000, PeriodicLimits: []gocardless.BillingRequestCreateParamsMandateRequestConstraintsPeriodicLimit{ { Period: "month", MaxTotalAmount: 100000, Alignment: "creation_date", }, }, }, }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response** ```json { "billing_requests": { "id": "BRQ0000301", "created_at": "2024-11-01T00:00:00.000Z", "status": "pending", "mandate_request": { "scheme": "faster_payments", "currency": "GBP", "verify": "recommended", "consent_type": "recurring", "description": null, "sweeping": false, "payer_requested_dual_signature": false, "metadata": {}, "links": {}, "constraints": { "start_date": "2024-11-01", "end_date": null, "max_amount_per_payment": 50000, "periodic_limits": [ { "period": "month", "max_total_amount": 100000, "alignment": "creation_date", "max_amount_per_period": null, "max_payments": null } ] } }, "payment_request": null, "subscription_request": null, "instalment_schedule_request": null, "metadata": {}, "fallback_enabled": true, "fallback_occurred": false, "purpose_code": "loan", "payment_purpose_code": "bank_loan_delayed_draw_funding", "sign_flow_url": null, "auto_fulfil": false, "actions": [ { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "collect_customer_details": { "default_country_code": "GB", "incomplete_fields": { "customer": ["given_name", "family_name", "email"], "customer_billing_detail": ["address_line1", "city", "postal_code", "country_code"] } } }, { "type": "select_institution", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "institution_guess_status": "pending" }, { "type": "collect_bank_account", "required": true, "completes_actions": [], "requires_actions": [], "status": "pending", "available_country_codes": ["GB"] }, { "type": "bank_authorisation", "required": true, "completes_actions": [], "requires_actions": ["select_institution", "collect_customer_details"], "status": "pending", "bank_authorisation": { "authorisation_type": "mandate" } }, { "type": "confirm_payer_details", "required": true, "completes_actions": [], "requires_actions": ["collect_customer_details", "collect_bank_account"], "status": "pending" } ], "links": { "mandate_request": "MRQ0000301" } } } ``` ### Confirm the mandate After creating the Billing Request, direct the customer to authorise the consent. How you do this depends on your integration type: - Hosted Pages - Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Payment Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages). - Custom API - Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). ### Handle the outcome Listen for webhooks to confirm the mandate status: | Event | Meaning | | ------------------------- | -------------------------------- | | billing_request_fulfilled | Customer authorised the mandate | | mandates_created | Mandate created and ready to use | | mandates_active | Mandate active | ### Collect a variable payment You can collect a payment with the customer not present (recurring billing etc.): ```http curl -X POST https://api.gocardless.com/payments \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: UNIQUE_KEY" \ -d '{ "payments": { "amount": 5000, "currency": "GBP", "psu_interaction_type": "off_session", "charge_date": "2024-11-01", "description": "November subscription", "links": { "mandate": "MD123" } } }' ``` ```php $response = $client->payments()->create( [ 'params' => [ 'amount' => 5000, 'currency' => 'GBP', 'psu_interaction_type' => 'off_session', 'charge_date' => '2024-11-01', 'description' => 'November subscription', 'links' => [ 'mandate' => 'MD123', ], ], ], 'UNIQUE_KEY' ); ``` ```python response = client.payments.create( params={ 'amount': 5000, 'currency': 'GBP', 'psu_interaction_type': 'off_session', 'charge_date': '2024-11-01', 'description': 'November subscription', 'links': { 'mandate': 'MD123', }, }, headers={'Idempotency-Key': 'UNIQUE_KEY'} ) ``` ```ruby response = client.payments.create( params: { amount: 5000, currency: 'GBP', psu_interaction_type: 'off_session', charge_date: '2024-11-01', description: 'November subscription', links: { mandate: 'MD123' } }, headers: { 'Idempotency-Key' => 'UNIQUE_KEY' } ) ``` ```java Payment payment = client.payments() .create() .withAmount(5000) .withCurrency("GBP") .withPsuInteractionType("off_session") .withChargeDate("2024-11-01") .withDescription("November subscription") .withLinksMandate("MD123") .withIdempotencyKey("UNIQUE_KEY") .execute(); ``` ```javascript const payment = await client.payments.create( { amount: 5000, currency: "GBP", psu_interaction_type: "off_session", charge_date: "2024-11-01", description: "November subscription", links: { mandate: "MD123", }, }, "UNIQUE_KEY", ); ``` ```cs var payment = await client.Payments.CreateAsync( new PaymentCreateRequest { Amount = 5000, Currency = "GBP", PsuInteractionType = "off_session", ChargeDate = "2024-11-01", Description = "November subscription", Links = new PaymentCreateRequest.PaymentLinks { Mandate = "MD123" } }, new RequestSettings { IdempotencyKey = "UNIQUE_KEY" } ); ``` ```go params := gocardless.PaymentCreateParams{ Amount: 5000, Currency: "GBP", PsuInteractionType: "off_session", ChargeDate: "2024-11-01", Description: "November subscription", Links: gocardless.PaymentCreateParamsLinks{ Mandate: "MD123", }, } payment, err := client.Payments.Create(context.TODO(), params, gocardless.WithIdempotencyKey("UNIQUE_KEY")) ``` Or when the customer is present for top-ups and one-off purchases: ```http curl -X POST https://api.gocardless.com/payments \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "payments": { "amount": 5000, "currency": "GBP", "psu_interaction_type": "in_session", "description": "One-off top-up", "links": { "mandate": "MD123" } } }' ``` ```php $response = $client->payments()->create([ 'params' => [ 'amount' => 5000, 'currency' => 'GBP', 'psu_interaction_type' => 'in_session', 'description' => 'One-off top-up', 'links' => [ 'mandate' => 'MD123', ], ], ]); ``` ```python response = client.payments.create( params={ 'amount': 5000, 'currency': 'GBP', 'psu_interaction_type': 'in_session', 'description': 'One-off top-up', 'links': { 'mandate': 'MD123', }, } ) ``` ```ruby response = client.payments.create( params: { amount: 5000, currency: 'GBP', psu_interaction_type: 'in_session', description: 'One-off top-up', links: { mandate: 'MD123' } } ) ``` ```java Payment payment = client.payments() .create() .withAmount(5000) .withCurrency("GBP") .withPsuInteractionType("in_session") .withDescription("One-off top-up") .withLinksMandate("MD123") .execute(); ``` ```javascript const payment = await client.payments.create({ amount: 5000, currency: "GBP", psu_interaction_type: "in_session", description: "One-off top-up", links: { mandate: "MD123", }, }); ``` ```cs var payment = await client.Payments.CreateAsync( new PaymentCreateRequest { Amount = 5000, Currency = "GBP", PsuInteractionType = "in_session", Description = "One-off top-up", Links = new PaymentCreateRequest.PaymentLinks { Mandate = "MD123" } } ); ``` ```go params := gocardless.PaymentCreateParams{ Amount: 5000, Currency: "GBP", PsuInteractionType: "in_session", Description: "One-off top-up", Links: gocardless.PaymentCreateParamsLinks{ Mandate: "MD123", }, } payment, err := client.Payments.Create(context.TODO(), params) ``` To cancel a future-dated payment (off-session only): `POST /payments//actions/cancel`. In-session payments cannot be cancelled once submitted. Listen for webhooks to confirm the variable payment status: | Event | Meaning | | ------------------ | ----------------------------- | | payments_confirmed | Payment confirmed and settled | | payments_failed | Payment failed | ### Handle the consent being cancelled Listen for webhooks to confirm the consent status: | **Event** | **Meaning** | | ------------------ | ---------------------------------------------------------------- | | mandates_cancelled | Consent cancelled (by you or the customer via their banking app) | ## sVRP: Step-by-step guide ### Create a Billing Request ```http curl -X POST https://api.gocardless.com/billing_requests \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "billing_requests": { "mandate_request": { "scheme": "faster_payments", "sweeping": true, "constraints": { "start_date": "2024-11-01", "end_date": "2025-11-01", "max_amount_per_payment": 50000, "periodic_limits": [{ "period": "month", "max_total_amount": 100000, "alignment": "creation_date" }] } } } }' ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->create([ 'params' => [ 'mandate_request' => [ 'scheme' => 'faster_payments', 'sweeping' => true, 'constraints' => [ 'start_date' => '2024-11-01', 'end_date' => '2025-11-01', 'max_amount_per_payment' => 50000, 'periodic_limits' => [ [ 'period' => 'month', 'max_total_amount' => 100000, 'alignment' => 'creation_date', ], ], ], ], ], ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.create( params={ 'mandate_request': { 'scheme': 'faster_payments', 'sweeping': True, 'constraints': { 'start_date': '2024-11-01', 'end_date': '2025-11-01', 'max_amount_per_payment': 50000, 'periodic_limits': [ { 'period': 'month', 'max_total_amount': 100000, 'alignment': 'creation_date', }, ], }, } } ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.create( params: { mandate_request: { scheme: 'faster_payments', sweeping: true, constraints: { start_date: '2024-11-01', end_date: '2025-11-01', max_amount_per_payment: 50000, periodic_limits: [ { period: 'month', max_total_amount: 100000, alignment: 'creation_date' } ] } } } ) ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequestCreateResponse response = client.billingRequests() .create() .withMandateRequestScheme("faster_payments") .withMandateRequestSweeping(true) .withMandateRequestConstraintsStartDate("2024-11-01") .withMandateRequestConstraintsEndDate("2025-11-01") .withMandateRequestConstraintsMaxAmountPerPayment(50000) .withMandateRequestConstraintsPeriodicLimitsBuilder() .withPeriod("month") .withMaxTotalAmount(100000) .withAlignment("creation_date") .done() .execute(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const response = await client.billingRequests.create({ mandate_request: { scheme: "faster_payments", sweeping: true, constraints: { start_date: "2024-11-01", end_date: "2025-11-01", max_amount_per_payment: 50000, periodic_limits: [ { period: "month", max_total_amount: 100000, alignment: "creation_date", }, ], }, }, }); ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var response = await client.BillingRequests.CreateAsync( new BillingRequestCreateRequest { MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "faster_payments", Sweeping = true, Constraints = new BillingRequestCreateRequest.BillingRequestMandateRequestConstraints { StartDate = "2024-11-01", EndDate = "2025-11-01", MaxAmountPerPayment = 50000, PeriodicLimits = new List { new BillingRequestCreateRequest.BillingRequestMandateRequestConstraintsPeriodicLimit { Period = "month", MaxTotalAmount = 100000, Alignment = "creation_date" } } } } } ); ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } sweeping := true params := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "faster_payments", Sweeping: &sweeping, Constraints: &gocardless.BillingRequestCreateParamsMandateRequestConstraints{ StartDate: "2024-11-01", EndDate: "2025-11-01", MaxAmountPerPayment: 50000, PeriodicLimits: []gocardless.BillingRequestCreateParamsMandateRequestConstraintsPeriodicLimit{ { Period: "month", MaxTotalAmount: 100000, Alignment: "creation_date", }, }, }, }, } result, err := client.BillingRequests.Create(context.TODO(), params) if err != nil { panic(err) } fmt.Println(result) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "pending", "mandate_request": { "currency": "GBP", "scheme": "faster_payments" }, "links": { "customer": "CU123", "customer_billing_detail": "CBD123", "mandate_request": "MRQ123" }, "actions": [ { "type": "collect_customer_details", "required": true, "status": "pending" }, { "type": "collect_bank_account", "required": true, "status": "pending" }, { "type": "bank_authorisation", "required": true, "status": "pending" } ] } } ``` ### Confirm the consent After creating the Billing Request, direct the customer to authorise the consent. How you do this depends on your integration type: - Hosted Pages - Create a Billing Request Flow and redirect the customer to the authorisation_url. See [Hosted Payment Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages). - Custom API - Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/docs/collect-payments/integration-types/custom-payment-pages). ### Handle the outcome Listen for webhooks to confirm the mandate status: | Event | Meaning | | ------------------------- | -------------------------------- | | billing_request_fulfilled | Customer authorised the mandate | | mandates_created | Mandate created and ready to use | | mandates_active | Mandate active | ### Collect a variable payment Retrieve the mandate ID from: ```http curl https://api.gocardless.com/billing_requests/BRQ000123 \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ```php getenv('GC_ACCESS_TOKEN'), 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $response = $client->billingRequests()->get('BRQ000123'); $mandateId = $response->mandate_request->links->mandate; ``` ```python client = gocardless_pro.Client( access_token=os.environ['GC_ACCESS_TOKEN'], environment='sandbox' ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: ENV['GC_ACCESS_TOKEN'], environment: :sandbox ) response = client.billing_requests.get('BRQ000123') mandate_id = response.mandate_request.links.mandate ``` ```java GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GC_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests() .get("BRQ000123") .execute(); String mandateId = billingRequest.getMandateRequest().getLinks().getMandate(); ``` ```javascript const gocardless = require("gocardless-nodejs"); const constants = require("gocardless-nodejs/constants"); const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox); const billingRequest = await client.billingRequests.find("BRQ000123"); const mandateId = billingRequest.mandate_request.links.mandate; ``` ```cs using GoCardless; var client = GoCardlessClient.Create( Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"), GoCardlessClient.Environment.SANDBOX ); var billingRequest = await client.BillingRequests.GetAsync("BRQ000123"); var mandateId = billingRequest.MandateRequest.Links.Mandate; ``` ```go package main "context" "fmt" "os" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts) if err != nil { panic(err) } billingRequest, err := client.BillingRequests.Get(context.TODO(), "BRQ000123") if err != nil { panic(err) } mandateId := billingRequest.MandateRequest.Links.Mandate fmt.Println(mandateId) } ``` **Response:** ```json { "billing_requests": { "id": "BRQ000123", "status": "fulfilled", "mandate_request": { "scheme": "bacs", "links": { "mandate": "MD123" } } } } ``` And collect a variable payment from the consent within the agreed constraints: ```http curl -X POST https://api.gocardless.com/payments \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "payments": { "amount": 10000, "currency": "GBP", "description": "Monthly savings sweep", "links": { "mandate": "MD123" } } }' ``` ```php $response = $client->payments()->create([ 'params' => [ 'amount' => 10000, 'currency' => 'GBP', 'description' => 'Monthly savings sweep', 'links' => [ 'mandate' => 'MD123', ], ], ]); ``` ```python response = client.payments.create( params={ 'amount': 10000, 'currency': 'GBP', 'description': 'Monthly savings sweep', 'links': { 'mandate': 'MD123', }, } ) ``` ```ruby response = client.payments.create( params: { amount: 10000, currency: 'GBP', description: 'Monthly savings sweep', links: { mandate: 'MD123' } } ) ``` ```java Payment payment = client.payments() .create() .withAmount(10000) .withCurrency("GBP") .withDescription("Monthly savings sweep") .withLinksMandate("MD123") .execute(); ``` ```javascript const payment = await client.payments.create({ amount: 10000, currency: "GBP", description: "Monthly savings sweep", links: { mandate: "MD123", }, }); ``` ```cs var payment = await client.Payments.CreateAsync( new PaymentCreateRequest { Amount = 10000, Currency = "GBP", Description = "Monthly savings sweep", Links = new PaymentCreateRequest.PaymentLinks { Mandate = "MD123" } } ); ``` ```go params := gocardless.PaymentCreateParams{ Amount: 10000, Currency: "GBP", Description: "Monthly savings sweep", Links: gocardless.PaymentCreateParamsLinks{ Mandate: "MD123", }, } payment, err := client.Payments.Create(context.TODO(), params) ``` **Response:** ```json { "payments": { "id": "PM123", "status": "pending_submission", "amount": 10000, "currency": "GBP", "charge_date": "2024-11-01", "links": { "mandate": "MD123" } } } ``` ### Handle the consent being cancelled Listen for webhooks to confirm the consent status: | **Event** | **Meaning** | | ------------------ | ---------------------------------------------------------------- | | mandates_cancelled | Consent cancelled (by you or the customer via their banking app) | ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates and collect bank account details via the API. #### [GoCardless Hosted Pages](/docs/collect-payments/integration-types/gocardless-hosted-pages) Use hosted pages for a no-code VRP integration. #### [VRP Events](/docs/collect-payments/events-and-webhooks/billing-request-events) Understand the webhook events fired during the VRP consent lifecycle. #### [Scheme Guidance](/docs/collect-payments/scheme-guidance/billing-request-purpose-codes) Purpose codes and scheme-specific requirements for VRP. ## Verified Mandates URL: https://docs.gocardless.com/docs/collect-payments/setting-up-mandates/verified-mandates > Set up verified mandates with bank account verification. # Verified Mandates > **Info:** > Verified Mandates is only available to approved integrators with the Verified Mandates upgrade. > This upgrade is enabled by default for merchants with Standard or Plus packages. [Contact > support](mailto:help@gocardless.com) to get access. This guide shows how to create a Verified Mandate by creating a Billing Request which opts-into customer bank account verification, and sending the customer through a GoCardless hosted [Billing Request Flow](/docs/api-reference/billing-request-flow#create-a-billing-request-flow) to complete the verification. By verifying the customer has access to the bank account the Direct Debit mandate will be created against, you can protect yourself against fraudulent payers. ### Before we begin: Availability and Preference Verified Mandates use different mechanisms depending on the scheme of the mandate in the Billing Request. Here is a full list of supported Bank Debit schemes, whether a verification mechanism is available, and whether scheme compliance requires a customer to perform the verification. | **Scheme** | **API** | **Available** | **Required by Scheme** | | ------------------- | ------------------ | --------------------- | ---------------------- | | 🇺🇸 ACH | `ach` | Yes | No | | 🇸🇪 Autogiro | `autogiro` | Yes | Yes | | 🇬🇧 Bacs | `bacs` | Yes | No | | 🇦🇺 BECS | `becs` | No | - | | 🇳🇿 BECS NZ | `becs_nz` | No | - | | 🇩🇰 Betalingsservice | `betalingsservice` | No | - | | 🇨🇦 PAD | `pad` | No | - | | 🇪🇺 SEPA Core | `sepa_core` | Germany 🇩🇪, France 🇫🇷 | No | To request verification for your mandate, you must set the `verify` attribute of the `mandate_request` to a level that matches your preference. Verification preference can be one of: - **minimum**: only verify if absolutely required, such as when part of scheme rules - **recommended**: in addition to `minimum`, use Protect+ to decide if a payer should be verified - **when_available**: if verification mechanisms are available, use them - **always**: as `when_available`, but fail to create the Billing Request if a mechanism isn't available > **Info:** > Protect+ is only available to approved integrators with the corresponding upgrade. If you're > interested in trying it out, please [contact support](mailto:help@gocardless.com). By default, all Billing Requests use the `recommended` verification preference. It uses Protect+ to determine if a payer is fraudulent or not. The verification mechanism is based on the response and the payer may be asked to verify themselves. If the feature is not available, `recommended` behaves like `minimum`. If you never wish to take advantage of Protect+ and Verified Mandates as they are released in new schemes, please use the `minimum` verification preference. > **Warning:** > Whilst we continually improve our verification flows, not all banks are available or supported and > some flows may fail due to device-specific issues. We recommend only setting `when_available` or > `always` when you are happy with some potential impact on conversion in favour of drastically > reduced risk. To help optimise your flows we advise using the `recommended` setting. This can be > combined with our anti-fraud product [Protect+](/docs/optimise/prevent-fraud-with-protect-plus) > for increased protection and verification while maintaining good conversion rates. ### How-to In this how-to, we'll opt for `when_available` to ensure we apply the verification if the scheme supports it. And as per our availability, we'll be creating a `bacs` mandate, as that scheme supports verification. Let's begin! > **Info:** > To test the flow in the sandbox environment you will need [a sandbox > account](https://manage-sandbox.gocardless.com/sign-in) and [test bank > details](/docs/api-reference/local-bank-details). ### Create a Billing Request Use the [Create a Billing Request](/docs/api-reference/billing-request#create-a-billing-request) endpoint: ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequests()->create([ "params" => [ "mandate_request" => [ "scheme" => "bacs", "verify" => "when_available" ] ] ]); ``` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_requests.create(params={ "mandate_request": { "scheme": "bacs", "verify": "when_available" } }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_requests.create( params: { mandate_request: { scheme: "bacs", verify: "when_available" } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequest billingRequest = client.billingRequests().create() .withMandateRequestScheme("bacs") .withMandateRequestVerify("when_available") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequest = await client.billingRequests.create({ mandate_request: { scheme: "bacs", verify: "when_available", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var mandateRequest = new GoCardless.Services.BillingRequestCreateRequest.BillingRequestMandateRequest { Scheme = "bacs", Verify = "when_available" }; var resp = await gocardless.BillingRequests.CreateAsync( new GoCardless.Services.BillingRequestCreateRequest() { MandateRequest = mandateRequest, } ); GoCardless.Resources.BillingRequest billingRequest = resp.BillingRequest; ``` ```http POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "bacs", "verify": "when_available" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) config, err := gocardless.NewConfig(accessToken, opts) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } billingRequestCreateParams := gocardless.BillingRequestCreateParams{ MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{ Scheme: "bacs", Verify: "when_available", }, } billingRequest, err := client.BillingRequests.Create(context, billingRequestCreateParams) ``` ```CLI gc create billing_request \ -d 'mandate_request[scheme]=bacs' \ -d 'mandate_request[verify]=when_available' ``` This will create a new Billing Request, asking for a Bacs mandate and requesting a `when_available` verification preference. The response will look like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": { "currency": "GBP", "scheme": "bacs", "verify": "when_available" }, "actions": [ { "type": "bank_authorisation", "required": true, "status": "pending" } ] } } ``` As Bacs supports verification, you'll see we have a `bank_authorisation` action in the Billing Request response. Note the action is required, which means we cannot fulfil this request without first completing the bank authorisation. We can use Billing Request Flows to generate a checkout flow that guides the payer through these actions, including the verification via bank authorisation. ### Create a Billing Request Flow Billing Request Flows can be created against Billing Requests, and provide an entry into a hosted GoCardless flow that completes whatever actions remain against the request. Create a Billing Request Flow to retrieve a link that can be provided to your customer to complete the request: ```php $client = new \GoCardlessPro\Client(array( 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX )); $client->billingRequestFlows()->create([ "params" => [ "redirect_uri" => "https://my-company.com/landing", "exit_uri" => "https://my-company.com/exit", "links" => [ "billing_request" => "BRQ000010NMDMH2" ] ] ]); ``` ```python client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.billing_request_flows.create(params={ "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.billing_request_flows.create( params: { redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", } } ) ``` ```java String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); BillingRequestFlow billingRequestFlow = client.billingRequestFlows().create() .withRedirectUri("https://my-company.com/landing") .withExitUri("https://my-company.com/exit") .withLinksBillingRequest("BRQ000010NMDMH2") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const billingRequestFlow = await client.billingRequestFlows.create({ redirect_uri: "https://my-company.com/landing", exit_uri: "https://my-company.com/exit", links: { billing_request: "BRQ000010NMDMH2", }, }); ``` ```cs String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var resp = await gocardless.BillingRequestFlows.CreateAsync( new GoCardless.Services.BillingRequestFlowCreateRequest() { RedirectUri = "https://my-company.com/landing", ExitUri = "https://my-company.com/exit", Links = new GoCardless.Services.BillingRequestFlowCreateRequest.BillingRequestFlowLinks { BillingRequest = "BRQ000010NMDMH2", }, } ); GoCardless.Resources.BillingRequestFlow billingRequestFlow = resp.BillingRequestFlow; ``` ```http POST https://api.gocardless.com/billing_request_flows HTTP/1.1 { "billing_request_flows": { "redirect_uri": "https://my-company.com/landing", "exit_uri": "https://my-company.com/exit", "links": { "billing_request": "BRQ000010NMDMH2" } } } ``` ```go package main gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here"; opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(accessToken, opts) billingRequestFlowCreateParams := gocardless.BillingRequestFlowCreateParams{} billingRequestFlowCreateParams.RedirectUri = "https://my-company.com/landing" billingRequestFlowCreateParams.ExitUri = "https://my-company.com/exit" billingRequestFlowCreateParams.Links.BillingRequest = "BRQ000010NMDMH2" billingRequestFlow, err := client.BillingRequestFlows.Create(context, billingRequestFlowCreateParams) ``` ```CLI gc create billing_request_flow \ -d "links[billing_request]= BRQ000010NMDMH2" \ -d 'redirect_uri=https://my-company.com/landing' \ -d 'exit_uri=https://my-company.com/exit' ``` This returns a new flow, which has an `authorisation_url` you should send to your customer: ```json { "billing_request_flows": { "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=", "lock_customer_details": false, "lock_bank_account": false, "auto_fulfil": true, "created_at": "2021-03-30T16:23:10.679Z", "expires_at": "2021-04-06T16:23:10.679Z", "redirect_uri": "https://my-company.com/completed", "links": { "billing_request": "BRQ123" } } } ``` ### Redirect customer to authorisation link Share your **authorisation link** from the response in Step 2, via a button on your website, SMS, email, or any other way you like. Preview what your customer will see by following the steps below. ### What the customer will see When the customer opens the authorisation link, they'll see a form that goes through the following steps. The example is shown for the 🇬🇧 **Bacs** scheme. ### Choose currency _**Note: This portion of the screen will only be visible if the organisation accepts multiple currencies.**_ Choose a currency to change the currency and scheme for the billing request. ![currency selector screenshot](/images/docs/collect-payments/setting-up-mandates/verified-mandates/01_choose_currency.png) ### Collect customer details _**Note: This screen is skipped if the details already exist, or the customer details have been locked.**_ Collect customer details in order to complete the billing request. ![bacs-01-customer-details](/images/docs/collect-payments/setting-up-mandates/verified-mandates/02_collect_customer_details.png) ### Collect bank details **_Optional step: This step is only required when `verify` is set to `recommended` or `minimum`._** Collect customer bank account details in order to complete the billing request. ![bacs-01b-bank-details](/images/docs/collect-payments/setting-up-mandates/verified-mandates/03_collect_bank_details.png) ### Select bank **_Optional step: This step is required only when verify is set to `always` or `when_available`. It is sometimes required in supported schemes when using `Protect+` upgrade and the `recommended` option._** Select bank in order to complete the billing request. ![bacs-01c-bank-select](/images/docs/collect-payments/setting-up-mandates/verified-mandates/04_select_bank.png) ### Start verification Customers can start the verification process by clicking `Agree and continue` and scanning the QR code. ![bacs-02-bank-connect-request](/images/docs/collect-payments/setting-up-mandates/verified-mandates/05_start_verification.png) This is an example of a possible verification mechanism, but different schemes and banks have different flows, and we reserve the right to change the mechanism to better suit specific schemes or business needs. ### Complete verification The customer should log in to their bank account and authorise GoCardless to read their details. This is an example of the Monzo mobile flow. ![bacs-03-bank-authorisation](/images/docs/collect-payments/setting-up-mandates/verified-mandates/bacs-03-bank-authorisation.png) ### Select bank account **_Optional step: This step is required only if the payer provided consent to access multiple accounts eligible for Direct Debit set up._** The customer should select the bank account they would like to set up Direct Debit with. ![bacs-03b-select-bank-account](/images/docs/collect-payments/setting-up-mandates/verified-mandates/07_select_bank_account.png) ### Confirm details Preview the details and Direct Debit guarantee (changes per scheme) before agreeing to set up the mandate. ![bacs-04-confirm-details](/images/docs/collect-payments/setting-up-mandates/verified-mandates/08_confirm_details.png) ### Success Everything has been set up, and we show a success screen before redirecting back to the Billing Request Flow `redirect_uri`. ![bacs-05-success](/images/docs/collect-payments/setting-up-mandates/4.jpg) ### Done! The Direct Debit mandate has now been created, and the Billing Request is `fulfilled`. Note that the mandate will have a `verified_at` timestamp set to the last successful verification, which can be used to identify which mandates have been verified. You can use the [Create Payments](/docs/api-reference/payment#create-a-payment) endpoint to create new payments against the mandate or use the mandate in other resources such as when [Creating a Subscription](/docs/api-reference/subscription#create-a-subscription). ### Examples in other schemes ### 🇺🇸 ACH For the ACH scheme, the verification is processed by the external provider. ![ach-flow-example-1](/images/docs/collect-payments/setting-up-mandates/verified-mandates/01_personal_details_and_access_info.png) ![ach-flow-example-2](/images/docs/collect-payments/setting-up-mandates/verified-mandates/02_plaid_flow.png) ![ACH VM Confirmation page](/images/docs/collect-payments/setting-up-mandates/verified-mandates/03_confirmation.png) ### 🇸🇪 Autogiro > **Info: BankId scenario simulators** > We recommend testing out the BankId success and failure scenarios using our sandbox environment > BankId scenario simulators by following the steps outlined in our > [guide](/docs/developer-resources/bankid-scenario-simulators). For the Autogiro scheme, it is a requirement to put all the payers setting up the Direct Debit Mandate through BankId verification. This means you will need the Verified Mandates upgrade enabled in order to have mandates set up in the Autogiro scheme. ![bankid-flow-example-1](/images/docs/collect-payments/setting-up-mandates/verified-mandates/01_bankid_collect_details.png) ![bankid-flow-example-2](/images/docs/collect-payments/setting-up-mandates/verified-mandates/02_bankid_screens.png) ![bankid-flow-example-3](/images/docs/collect-payments/setting-up-mandates/verified-mandates/03_confirmation-2.png) ### Frequently asked questions ### How can I test this flow if I have the upgrade for using Protect+? Set the `verify` option on the `billing_request` to `always` to test the flow. This means that the institution the payer is trying to use is not supported by our Account Information Service (AIS) provider. ![bacs-verified-mandates-bank-not-supported](/images/docs/collect-payments/setting-up-mandates/verified-mandates/bacs-verified-mandates-bank-not-supported.png) ### How do I know if the verification was successful? A timestamp for `authorised_at` will be set on the `bank_authorisation` resource for the billing request. The created mandate will also include a 'verified' badge next to the Mandate verification status on the merchant dashboard. ![bacs-verified-mandate-badge](/images/docs/collect-payments/setting-up-mandates/verified-mandates/bacs-verified-mandate-badge.png) ## What's next? #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create standard Direct Debit mandates using the Billing Requests API. #### [Billing Request Events](/docs/collect-payments/events-and-webhooks/billing-request-events) Handle events fired during the verified mandate setup flow. #### [Offline Mandates](/docs/collect-payments/setting-up-mandates/offline-mandates) Collect mandates via paper or phone authorisation. #### [Protect+](/docs/optimise/prevent-fraud-with-protect-plus) Use Protect+ with the recommended verification setting for optimal conversion and fraud protection. ## VRP Commercial Payment Purpose Codes URL: https://docs.gocardless.com/docs/collect-payments/scheme-guidance/vrp-purpose-codes > Purpose codes for VRP commercial payments. # Payment purpose codes for VRP Commercial | **Values** | **Definition** | **Description** | | ---------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | `bank_loan_delayed_draw_funding` | Delayed draw funding. | Lender holding funds in reserve for the borrower to use later. | | `bank_loan_fees` | Bank loan fees. | Payment for loan admin fees, setup fees, or commitment fees. | | `bank_loan_funding_memo` | Bank loan funding memo. | Finalizing the cash movement for a loan contract. | | `bank_loan_accrued_interest_payment` | Accrued interest payments. | Paying interest that has built up on a bank loan. | | `bank_loan_principal_paydown` | Principal paydowns. | Paying back the main loan amount (not the interest). | | `card_bulk_clearing` | Service settling money for a bulk of card transactions. | Batch settlement for a group of card payments. | | `card_payment_with_cash_back` | Purchase of Goods/Services with Cash disbursement (Cashback). | Buying something at a store and getting cash back at the register. | | `cash_disbursement_cash_settlement` | ATM Cash Withdrawal or Cash Advance. | Getting cash from an ATM or bank teller. | | `cash_disbursement_with_surcharging` | ATM Cash Withdrawal/Advance with surcharging. | Getting cash from an ATM where an extra fee was charged. | | `card_deferred_payment` | Deferred Payment (e.g., petrol pumps). | Authorizing a card for a temporary amount (like at a gas pump) before the final charge. | | `original_credit` | Original Credit (e.g., gaming winnings). | Receiving money to your card (like gambling winnings) without a previous refund. | | `quasi_cash` | Purchase of Goods equivalent to cash (e.g., casino chips). | Buying items that act like cash, such as casino chips. | | `e_purse_top_up` | E-purse load. | Loading money onto a digital wallet or electronic purse. | | `fee_collection` | Fee collection. | Settling transaction fees between two financial parties. | | `mobile_top_up` | Mobile top-up. | Loading credit onto a prepaid mobile phone. | | `account_management` | Intra-account transfer. | Moving money between two accounts owned by the same person at the same bank. | | `cash_management_transfer` | General cash management. | General movement of funds for cash management purposes. | | `collection_payment` | Collection (Credit transfer or Direct Debit). | Pulling funds from another account (like a standard bill payment or direct debit). | | `cash_disbursement_cash_management` | Cash disbursement. | Paying out cash. | | `deposit` | Payment of deposit. | Placing a deposit for a service or purchase. | | `intra_company_payment` | Intra-company payment. | Moving money between two companies in the same corporate group. | | `intra_party_payment` | Intra-party payment. | Moving money between accounts owned by the same person (private individual). | | `liquidity_management` | Liquidity Management (Pooling/Sweeping). | Automatic transfer to clear a balance or pool money into a master account. | | `netting` | Netting operation. | Settling the difference between what is owed and what is due, rather than the full amounts. | | `bond_forward` | Bond Forward collateral. | Security deposit (cash) for bond trades settling more than 3 days out. | | `cross_currency_irs` | Cross Currency IRS Collateral. | Collateral for swapping interest payments in different currencies. | | `ccp_cleared_initial_margin` | CCP Initial Margin. | Initial security deposit required to trade via a Central Counterparty Clearing house. | | `ccp_cleared_variation_margin` | CCP Variation Margin. | Adjustment payment to cover daily profit/loss changes on CCP trades. | | `ccp_cleared_initial_margin_segregated_cash` | CCP Segregated initial margin. | Initial margin held in a separate, safe account for CCP trades. | | `credit_default_swap` | Credit default swap collateral. | Collateral related to trading insurance against loan defaults (CDS). | | `cross_product` | Cross Product collateral. | Collateral covering a mix of different trade types. | | `credit_support` | Credit Support collateral. | Collateral for lending/borrowing or master agreements. | | `credit_line` | Credit Line collateral. | Collateral put up to open a line of credit. | | `equity_option` | Equity Option collateral. | Collateral for trading stock options. | | `equity_swap` | Equity Swap collateral. | Collateral for swapping stock returns for interest rates. | | `exotic_option` | Exotic Option collateral. | Collateral for trading complex/non-standard options. | | `exchange_traded_derivatives` | Exchange Traded Derivatives collateral. | Collateral for derivatives traded on a public exchange (not private/OTC). | | `fixed_income` | Fixed Income collateral. | Collateral related to bond/debt instrument trading. | | `forward_broker_owned_cash_collateral` | Forward Agreement collateral (Segregated). | Collateral for forward contracts, held in a locked account (client can't touch it). | | `forward_client_owned_cash_collateral` | Forward Agreement collateral (Client Owned). | Collateral for forward contracts, but the client retains ownership/use. | | `forward_broker_owned_cash_collateral_segregated` | Forward Agreement collateral (Broker Owned). | Collateral for forwards where the broker holds/owns the funds in a segregated account. | | `forward_client_owned_segregated_cash_collateral` | Forward Agreement collateral (Client Available). | Collateral for forwards owned by the client and returned to them for use. | | `daily_margin_on_listed_derivatives` | Daily margin on listed derivatives. | Daily payment to cover losses/gains on futures or options. | | `mbs_broker_owned_cash_collateral` | MBS Broker Owned Segregated Collateral. | Collateral for Mortgage-Backed Securities, held by the broker. | | `mbs_client_owned_cash_collateral` | MBS Client Owned Segregated Collateral. | Collateral for Mortgage-Backed Securities, owned by the client. | | `futures_initial_margin` | Initial futures margin (Client). | Initial deposit for futures trading, owned by the client. | | `futures_initial_margin_client_owned_segregated_cash_collateral` | Margin Client Owned Segregated Collateral. | Initial futures margin held in a separate safe account, owned by the client. | | `client_owned_occ_pledged_collateral` | OCC Pledged Collateral. | Collateral eligible to be pledged to the Options Clearing Corporation. | | `otc_option_broker_owned_cash_collateral` | OTC Option Collateral (Segregated). | Collateral for private option trades, held in a locked account. | | `otc_option_client_owned_cash_collateral` | OTC Option Collateral (Available). | Collateral for private option trades, available for client use. | | `otc_option_broker_owned_segregated_cash_collateral` | Option Broker Owned Segregated Collateral. | Collateral for options held/owned by the broker in a separate account. | | `otc_option_client_owned_cash_segregated_cash_collateral` | Option Client Owned Segregated Collateral. | Collateral for options owned by the client in a separate account. | | `fx_option` | FX Option collateral. | Collateral for trading options on foreign currency. | | `otc_derivatives` | OTC Derivatives collateral. | Collateral for general private (Over-The-Counter) derivative trades. | | `repurchase_agreement` | Repurchase agreement collateral. | Cash exchanged as part of a Repo deal (selling securities to buy them back later). | | `bilateral_repo_broker_owned_collateral` | Repo Broker Owned Collateral. | Repo collateral held by the broker. | | `repo_client_owned_collateral` | Repo Client Owned Collateral. | Repo collateral owned by the client. | | `bilateral_repo_broker_owned_segregated_cash_collateral` | Repo Broker Segregated Collateral. | Repo collateral held by the broker in a separate account. | | `bilateral_repo_client_owned_segregated_cash_collateral` | Repo Client Segregated Collateral. | Repo collateral owned by the client in a separate account. | | `reverse_repurchase_agreement` | Reverse Repo collateral. | Collateral for the other side of a Repo (buying securities to sell back later). | | `securities_buy_sell_sell_buy_back` | Securities Buy/Sell Back collateral. | Collateral for a specific type of securities financing transaction. | | `single_currency_irs_exotic` | Exotic Single Currency IRS collateral. | Collateral for complex interest rate swaps in one currency. | | `single_currency_irs` | Single Currency IRS collateral. | Collateral for standard interest rate swaps in one currency. | | `securities_cross_products` | Securities Cross Product collateral. | Collateral covering a mix of security types. | | `broker_owned_collateral_short_sale` | Short Sale Broker Collateral. | Collateral held by a broker to cover a short sale (betting against a stock). | | `client_owned_collateral_short_sale` | Short Sale Client Collateral. | Collateral owned by the client to cover a short sale. | | `short_sell` | Short Sell collateral. | General collateral related to short selling. | | `securities_lending_and_borrowing` | Securities Lending/Borrowing collateral. | Cash exchanged when lending or borrowing stocks/bonds. | | `secured_loan` | Secured Loan collateral. | Collateral pledged to secure a loan. | | `swap_broker_owned_cash_collateral` | Swap Collateral (Segregated). | Collateral for swaps held in a locked account (client cannot use). | | `swap_client_owned_cash_collateral` | Swap Collateral (Available). | Collateral for swaps available for client use. | | `swaption` | Swaption collateral. | Collateral for an option to enter into a swap. | | `swaps_broker_owned_segregated_cash_collateral` | Swap Broker Segregated Collateral. | Swap margin held by the broker in a separate account. | | `swaps_client_owned_segregated_cash_collateral` | Swap Client Segregated Collateral. | Swap margin owned by the client in a separate account. | | `to_be_announced` | TBA (To Be Announced) collateral. | Collateral for mortgage securities where the specific pool isn't known yet. | | `tba_broker_owned_cash_collateral` | TBA Collateral (Segregated). | TBA collateral held in a locked account. | | `tba_client_owned_cash_collateral` | TBA Collateral (Available). | TBA collateral available for client use. | | `treasury_cross_product` | Treasury Cross Product collateral. | Collateral covering a mix of treasury-related exposures. | | `agricultural_transfer` | Agriculture payment. | Payment related to farming or agriculture. | | `accounts_receivables_entry` | Accounts Receivable. | Collecting money owed to a business. | | `business_expenses` | Business expenses. | Reimbursement or payment of general business costs. | | `back_office_conversion_entry` | Back Office Conversion. | Processing a check as an electronic transfer (back office). | | `commercial_payment` | Commercial credit/debit. | General business-to-business payment. | | `copyright` | Copyright payment. | Paying for the right to use copyrighted material. | | `purchase_sale_of_goods` | Goods. | Payment for physical products. | | `purchase_sale_of_goods_and_services` | Goods and Services. | Payment for a mix of products and services. | | `purchase_sale_of_goods_and_services_with_cash_back` | Goods and Services with Cashback. | Buying items and getting cash back in the same transaction. | | `license_fee` | License fee. | Payment for a license (software, professional, etc.). | | `mobile_p2b_payment` | Mobile Person-to-Business. | Using a mobile app to pay a business/merchant. | | `point_of_purchase_entry` | Point of Purchase Entry. | A check converted to an electronic transfer at the cash register. | | `royalties` | Royalties. | Paying royalties (e.g., to an author or musician). | | `purchase_sale_of_services` | Services. | Payment for services rendered (consulting, labor, etc.). | | `service_charges` | Service charges. | Fees charged by a service provider. | | `subscription` | Subscription. | Recurring payment for magazines, Netflix, software, etc. | | `supplier_payment` | Supplier payment. | Paying a vendor for supplies. | | `trade_commercial` | Trade services. | Payment related to import/export or trade finance. | | `charity_payment` | Charity. | Donation to a charitable organization. | | `consumer_third_party_consolidated_payment` | Consumer Third Party Consolidation. | Payment to a bill consolidation service or credit counselor. | | `mobile_p2p_payment` | Mobile Person-to-Person. | Sending money to a friend via a mobile app using their phone number/alias. | | `guaranteed_e_payment` | E-Commerce (Guaranteed). | Online purchase where the bank guarantees the payment. | | `e_payment_return` | E-Commerce Return. | Refund for an online purchase. | | `non_guaranteed_e_payment` | E-Commerce (Not Guaranteed). | Standard online purchase without bank guarantee. | | `e_payment` | ePayment. | General electronic payment. | | `car_loan_principal_repayment` | Car Loan Principal. | Paying down the balance of a car loan. | | `compensation_payment` | Compensation. | Payment for interest loss or value date adjustments. | | `debit_collection_payment` | Debit Transfer Collection. | Collecting funds via debit transfer. | | `government_insurance` | Government Insurance. | Paying for government-backed insurance. | | `property_loan_repayment` | Property Loan Repayment. | Paying a mortgage or property loan installment. | | `property_loan_settlement` | Property Loan Settlement. | Paying off a property loan entirely. | | `insurance_premium_car` | Car Insurance Premium. | Paying for car insurance. | | `insurance_premium_refund` | Insurance Premium Refund. | Getting money back from an insurance company. | | `payment_of_insurance_claim` | Insurance Claim Payment. | Receiving a payout for an insurance claim. | | `insurance_premium` | Insurance Premium. | General payment for insurance coverage. | | `interest` | Interest. | Payment of interest. | | `labor_insurance` | Labor Insurance. | Paying for worker/labor insurance. | | `life_insurance` | Life Insurance. | Paying life insurance premiums. | | `loan` | Loan Transfer. | Disbursing a loan to a borrower. | | `loan_repayment` | Loan Repayment. | Repaying a loan to a lender. | | `payment_based_on_enforcement_order` | Enforcement Order. | Court-ordered payment (excluding alimony). | | `property_insurance` | Property Insurance. | Paying for home/property insurance. | | `rental_lease_general` | Rent/Lease. | General payment for rent or leasing. | | `recurring_installment_payment` | Recurring Installment. | Regular repeating payment (like a subscription or plan). | | `trust_fund` | Trust Fund. | Payment related to a trust fund. | | `forward_foreign_exchange` | FX Forward. | Currency trade settling in the future. | | `foreign_exchange_related_netting` | FX Netting. | Moving the net cash difference for a foreign exchange deal. | | `administrative_management` | Admin Management. | Payment for administrative services. | | `advance_payment` | Advance payment. | Paying for something before receiving it. | | `bearer_cheque_domestic` | Domestic Bearer Cheque. | Cashing a domestic check made out to "Bearer" (whoever holds it). | | `bearer_cheque_foreign` | Foreign Bearer Cheque. | Cashing a foreign check made out to "Bearer". | | `building_maintenance` | Building Maintenance. | Paying for building repairs or upkeep. | | `bond_forward_netting` | Bond Forward Netting. | Settling the net cash difference for bond forwards. | | `capital_building` | Capital Building. | Savings or investment for general capital growth. | | `capital_building_retirement` | Retirement Capital Building. | Savings specifically for retirement. | | `credit_card_payment` | Credit Card Payment. | Paying off a credit card balance. | | `credit_card_bill` | Credit Card Bill. | Payment of a credit card bill. | | `cancellation_fee` | Cancellation Fee. | Fee paid for cancelling a service or contract. | | `card_generated_direct_debit` | Card Generated Direct Debit. | A direct debit set up using card details at a point of sale. | | `trade_settlement_payment` | Trade Settlement. | Finalizing a financial trade (FX or securities). | | `costs` | Costs. | General payment of costs. | | `carpark_charges` | Carpark Charges. | Paying for parking. | | `debit_card_payment` | Debit Card Payment. | General payment using a debit card. | | `printed_order_disbursement` | Disbursement (Printed Order). | Payout from a specific bank/post office money order. | | `deliver_against_payment` | Delivery vs Payment (Pre-advise). | Warning that a "securities for cash" swap is coming. | | `education` | Education/Tuition. | Paying school or university fees. | | `factor_update_related_payment` | Factor Update. | Payment related to factoring (selling invoices for cash). | | `financial_aid_in_case_of_natural_disaster` | Disaster Aid. | Financial aid for natural disasters. | | `late_payment_of_fees_and_charges` | Late Fees/Charges. | Paying penalty fees (e.g., late credit card payment). | | `payment_of_fees` | Fees. | General payment of fees. | | `gift` | Gift. | Sending money as a gift (non-commercial). | | `government_payment` | Government Payment. | Payment to or from a government department. | | `irrevocable_credit_card_payment` | Credit Card Reimbursement. | Getting money back onto a credit card. | | `irrevocable_debit_card_payment` | Debit Card Reimbursement. | Getting money back onto a debit card. | | `installment_hire_purchase_agreement` | Installment/Hire-Purchase. | Paying off an item in installments (Rent-to-own). | | `installment` | Installment. | General installment payment. | | `invoice_payment` | Invoice Payment. | Paying a specific invoice. | | `multi_currency_cheque_domestic` | Domestic Multi-currency Cheque. | Paying a local check written in a different currency. | | `multi_currency_cheque_foreign` | Foreign Multi-currency Cheque. | Paying a foreign check written in a different currency. | | `multiple_service_types` | Multiple Services. | Payment covering various different services. | | `not_otherwise_specified` | Not Otherwise Specified. | Payment for a service that doesn't fit other codes. | | `order_cheque_domestic` | Domestic Order Cheque. | Payment of a standard domestic check. | | `order_cheque_foreign` | Foreign Order Cheque. | Payment of a standard foreign check. | | `opening_fee` | Opening Fee. | Fee paid to open an account or service. | | `other` | Other. | Catch-all for payments that don't fit any other category. | | `preauthorized_debit` | Pre-authorized Debit. | Initiating a direct debit agreed upon in advance. | | `payment_terms` | Payment Terms. | Payment related to specific terms. | | `represented_check_entry` | Re-presented Check. | Trying to cash a check again after it bounced previously. | | `receipt_payment` | Receipt. | Payment related to a receipt. | | `rebate` | Rebate. | Paying a rebate (returning part of a payment). | | `refund` | Refund. | Returning money for a return or error. | | `rent` | Rent. | Paying rent for housing or property. | | `account_overdraft_repayment` | Overdraft Repayment. | Paying back money owed to the bank for going over balance. | | `reimbursement_of_a_previous_erroneous_transaction` | Reimbursement. | Paying someone back for an erroneous transaction. | | `bilateral_repo_interest_netting` | Repo Interest Netting. | Settling interest differences on Repurchase Agreements. | | `round_robin` | Round Robin. | Cash payment resulting from a specific circular trading strategy. | | `reimbursement_received_credit_transfer` | Commercial Reimbursement. | Returning a valid payment for commercial reasons. | | `related_request_to_pay` | Request to Pay. | Response to a formal digital request for payment. | | `receive_against_payment` | Receive vs Payment (Pre-advise). | Warning that a "cash for securities" swap is coming. | | `payment_slip_instruction` | Payment Slip. | Payment made using a standardized bank slip. | | `split_payments` | Split Payments. | Separating cash and security movements for a trade. | | `study` | Study Costs. | Payment for tuition or study materials. | | `tba_pair_off_netting` | TBA Netting. | Settling net cash differences for TBA securities. | | `telecommunications_bill` | Telecom Bill. | Paying a phone or internet bill. | | `town_council_service_charges` | Town Council Charges. | Paying local municipality fees. | | `telephone_initiated_transaction` | Telephone Initiated. | Payment started over a phone call. | | `tmpg_claim_payment` | TMPG Claim. | Penalty payment for failing to deliver securities on time (US Treasury market). | | `tri_party_repo_interest` | Tri-Party Repo Interest. | Interest payment on a repo deal managed by a third party agent. | | `tri_party_repo_netting` | Tri-Party Repo Gain/Loss. | Net cash movement on a third-party managed repo. | | `truncated_payment_slip` | Truncated Payment Slip. | Payment where some beneficiary info is hidden/shortened. | | `traveller_cheque` | Travellers Cheque. | Buying or paying out a travellers cheque. | | `internet_initiated_transaction` | Internet Initiated. | Payment started online (web banking). | | `instant_payments` | Instant Payment. | Immediate transfer available to the receiver instantly. | | `instant_payments_cancellation` | Instant Payment Return. | Fully returning an instant payment. | | `instant_payments_for_donations` | Instant Donation. | Instant payment for charity (sharing payer address). | | `instant_payments_in_e_commerce_without_address_data` | Instant E-Commerce (No Address). | Instant online purchase (payer address hidden). | | `instant_payments_in_e_commerce_with_address_data` | Instant E-Commerce (Address). | Instant online purchase (payer address shared). | | `instant_payments_in_e_commerce` | Instant E-Commerce. | General instant online purchase. | | `instant_payments_at_pos` | Instant POS Payment. | Instant payment at a store register (Point of Sale). | | `instant_payments_return` | Instant Return (Partial/Full). | Returning part or all of an instant payment. | | `instant_payments_unattended_vending_machine_with_2fa` | Vending Machine (2FA). | Payment at a vending machine using 2-factor auth. | | `instant_payments_unattended_vending_machine_without_2fa` | Vending Machine (No 2FA). | Payment at a vending machine without 2-factor auth. | | `annuity` | Annuity. | Regular annual payment (investment, insurance, etc.). | | `custodian_management_fee_inhouse` | Custodian Fee. | Fee paid to the bank holding your assets. | | `capital_falling_due_inhouse` | Capital Falling Due. | Payment of capital maturity (e.g., a bond expiring). | | `commodity_transfer` | Commodities. | Payment for raw materials (oil, gold, wheat). | | `derivatives` | Derivatives. | General payment related to derivative trading. | | `dividend` | Dividend. | Payout of company profits to shareholders. | | `foreign_exchange` | Foreign Exchange. | General currency exchange transaction. | | `hedging` | Hedging. | Transaction made to reduce financial risk. | | `investment_and_securities` | Investment. | Buying mutual funds, shares, or products. | | `precious_metal` | Precious Metal. | Buying/selling gold, silver, etc. | | `savings` | Savings Transfer. | Moving money to a savings or retirement account. | | `securities` | Securities. | Buying/selling stocks or bonds. | | `securities_purchase_inhouse` | Securities Purchase. | Buying securities where the bank acts as custodian. | | `treasury_payment` | Treasury Operations. | General corporate treasury transaction. | | `unit_trust_purchase` | Unit Trust. | Buying into a Unit Trust fund. | | `futures_netting_payment` | Futures Netting. | Settling net cash for futures trades. | | `futures` | Futures. | General cash related to futures trading. | | `anesthesia_services` | Anesthesia Services. | Medical bill: Anesthesia. | | `convalescent_care_facility` | Convalescence Care. | Medical bill: Recovery facility. | | `durable_medical_equipment` | Durable Medical Equipment. | Medical bill: Equipment (wheelchairs, crutches, etc.). | | `dental_services` | Dental Services. | Medical bill: Dentist. | | `home_health_care` | Home Health Care. | Medical bill: Care provided at home. | | `health_insurance` | Health Insurance. | Paying health insurance premiums. | | `hospital_care` | Hospital Care. | Medical bill: Hospital stay/services. | | `intermediate_care_facility` | Intermediate Care. | Medical bill: Nursing home/intermediate care. | | `long_term_care_facility` | Long-term Care. | Medical bill: Long-term care facility. | | `medical_aid_fund_contribution` | Medical Aid Contribution. | Contributing to a medical aid fund. | | `medical_aid_refund` | Medical Aid Refund. | Refund from a medical aid fund. | | `medical_services` | Medical Services. | General medical bill. | | `vision_care` | Vision Care. | Medical bill: Optometrist/glasses. | | `credit_default_event_payment` | Credit Default Event. | Payment triggered because a borrower defaulted. | | `swap_contract_final_payment` | Swap Final Payment. | The last payment to close a swap contract. | | `swap_contract_partial_payment` | Swap Partial Payment. | Partial payment on a swap contract. | | `swap_contract_reset_payment` | Swap Reset. | Payment adjusting the terms/rates of a swap. | | `swap_contract_upfront_payment` | Swap Upfront. | Initial payment to start a swap contract. | | `advisory_donation_copyright_services` | Advisory/Donation/Copyright. | Payment for consulting, donations, or IP rights. | | `active_employment_policy` | Active Employment Policy. | Government payment related to job creation/support. | | `allowance` | Allowances. | Payment of a regular allowance. | | `alimony_payment` | Alimony. | Court-ordered spousal support. | | `baby_bonus_scheme` | Baby Bonus. | Government incentive for having children. | | `child_benefit` | Child Benefit. | Payment to help raise a child. | | `unemployment_disability_benefit` | Unemployment/Disability Benefit. | Payment to unemployed or disabled persons. | | `bonus_payment` | Bonus. | Performance bonus payment. | | `cash_compensation_helplessness_disability` | Cash Compensation. | Gov payment for helplessness/disability (extra social benefit). | | `commission` | Commission. | Payment based on sales performance. | | `company_social_loan_payment_to_bank` | Social Loan Financing. | Company paying a bank to fund loans for employees. | | `guarantee_fund_rights_payment` | Insolvency Compensation. | Paying unemployed staff when a company goes bankrupt. | | `austrian_government_employees_category_a` | Austrian Gov Employees A. | Salary for Austrian Gov Category A. | | `austrian_government_employees_category_b` | Austrian Gov Employees B. | Salary for Austrian Gov Category B. | | `austrian_government_employees_category_c` | Austrian Gov Employees C. | Salary for Austrian Gov Category C. | | `austrian_government_employees_category_d` | Austrian Gov Employees D. | Salary for Austrian Gov Category D. | | `government_war_legislation_transfer` | War Victim Payment. | Compensation to war victims or disabled soldiers. | | `housing_related_contribution` | Housing Contribution. | Employer paying towards an employee's housing (tax benefit). | | `payroll` | Payroll. | General payroll payment. | | `pension_fund_contribution` | Pension Fund Contribution. | Paying into a pension pot. | | `pension_payment` | Pension. | Monthly pension payout. | | `price_payment` | Price Payment. | Payment of a specific price. | | `rehabilitation_support` | Rehabilitation Benefit. | Payment while someone is in occupational rehab. | | `salary_payment` | Salary. | Standard monthly salary. | | `salary_pension_sum_payment` | Salary/Pension Split. | Lump sum salary/pension covering multiple months. | | `social_security_benefit` | Social Security Benefit. | Government support payment. | | `lending_buy_in_netting` | Lending Buy-in. | Cost to buy securities when a trade fails due to a lending issue. | | `lending_cash_collateral_free_movement` | Lending Collateral. | Cash collateral moved separately from the loaned shares. | | `lending_fees` | Lending Fees. | Fees for securities lending (admin, transaction, etc.). | | `lending_equity_marked_to_market_cash_collateral` | Equity Mark-to-Market. | Adjusting collateral based on changes in stock prices. | | `lending_fixed_income_marked_to_market_cash_collateral` | Fixed Income Mark-to-Market. | Adjusting collateral based on changes in bond prices. | | `lending_unspecified_type_of_marked_to_market_cash_collateral` | General Mark-to-Market. | Adjusting collateral based on market price changes. | | `lending_rebate_payments` | Lending Rebate. | Rebate paid in a securities lending deal. | | `lending_revenue_payments` | Lending Revenue. | Profit paid by the lending agent to the client. | | `lending_claim_payment` | Late Recall Fails. | Penalty paid for failing to return borrowed shares on time. | | `estate_tax` | Estate Tax. | Tax on a deceased person's estate. | | `foreign_worker_levy` | Foreign Worker Levy. | Tax/fee for hiring foreign workers. | | `goods_services_tax` | Goods & Services Tax. | Paying GST. | | `housing_tax` | Housing Tax. | Tax on housing/property. | | `income_tax` | Income Tax. | Tax on personal or corporate income. | | `net_income_tax` | Net Income Tax. | Tax on net income. | | `property_tax` | Property Tax. | Tax on property ownership. | | `road_tax` | Road Tax. | Tax for vehicle use on roads. | | `tax_payment` | Tax. | General tax payment. | | `value_added_tax_payment` | Value Added Tax. | Paying VAT. | | `with_holding` | Withholding Tax. | Tax deducted at source (e.g., from dividends). | | `tax_refund` | Tax Refund. | Refund of overpaid taxes. | | `trailer_fee_payment` | 12b-1 Fee. | US Mutual Fund marketing/distribution fee. | | `trailer_fee_rebate` | 12b-1 Rebate. | Refund of a US Mutual Fund fee. | | `non_us_mutual_fund_trailer_fee_payment` | Trailer Fee. | Commission paid to a salesperson for keeping a client in a fund (Non-US). | | `non_us_mutual_fund_trailer_fee_rebate_payment` | Trailer Rebate. | Refund of a trailer fee (Non-US). | | `air` | Air Transport. | Paying for business-related air travel. | | `bus` | Bus Transport. | Paying for business-related bus travel. | | `ferry` | Ferry Transport. | Paying for business-related ferry travel. | | `railway` | Railway Transport. | Paying for business-related train travel. | | `road_pricing` | Transport Top-up. | Loading money onto a transport card or road toll pass. | | `cable_tv_bill` | Cable TV Bill. | Paying for cable television. | | `electricity_bill` | Electricity Bill. | Paying for power/electric. | | `energies` | Utility Operation. | General utility payment. | | `gas_bill` | Gas Bill. | Paying for natural gas. | | `network_charge` | Network Charges. | Paying for network access infrastructure. | | `network_communication` | Network Communication. | Paying for internet/comms services. | | `other_telecom_related_bill` | Other Telecom Bill. | Telecom bill not covered by other codes. | | `telephone_bill` | Telephone Bill. | Paying for landline or mobile service. | | `utilities` | Utility Bill. | Common bill for Gas, Water, and Electricity combined. | | `water_bill` | Water Bill. | Paying for water supply. | | `bonds` | Bond Settlement. | Finalizing a bond trade (Securities Lending). | | `corporate_actions_bonds` | Corporate Action (Bonds). | Payment related to an event affecting a bond (e.g., restructuring). | | `corporate_actions_equities` | Corporate Action (Equities). | Payment related to an event affecting a stock (e.g., merger). | | `credit_card` | Credit Card Settlement. | Bank settling credit card transactions. | | `debit_card` | Debit Card Settlement. | Bank settling debit card transactions. | | `diners` | Diners Club Settlement. | Bank settling Diners Club transactions. | | `equities` | Equities Settlement. | Finalizing a stock trade (Securities Lending). | | `fleet_card` | Fleet Card Settlement. | Bank settling fleet (corporate vehicle) card transactions. | | `low_value_credit` | Low Value Credit (Utilities). | Small credit adjustment for utilities. | | `low_value_debit` | Low Value Debit (Utilities). | Small debit adjustment for utilities. | | `money_market` | Money Market Settlement. | Settling short-term borrowing/lending. | | `rapid_payment_instruction` | Rapid Payment Settlement. | Finalizing a batch of instant payments. | | `gambling_or_wagering_payment` | Gambling. | Payment for betting or collecting winnings. | | `lottery_payment` | Lottery. | Buying a lottery ticket or collecting winnings. | | `amex` | AMEX Settlement. | Bank settling American Express transactions. | | `atm` | ATM Settlement. | Bank settling ATM transactions. | | `authenticated_collections` | Authenticated Collections. | Verified collection of funds (Utility). | | `property_completion_payment` | Property Purchase Complete. | Final payment to buy a house/property. | | `property_deposit` | Property Deposit. | Initial deposit to buy a house/property. | | `property_loan_disbursement` | Property Loan Disbursement. | Bank releasing the mortgage funds to the buyer. | | `property_loan_refinancing` | Property Refinance. | Moving a mortgage to a new lender (no house sale involved). | | `government_family_allowance` | Family Allowance. | Gov payment to support families. | | `government_housing_allowance` | Housing Allowance. | Gov payment to help with rent/housing costs. | | `cash_penalties` | Cash Penalties (CSDR). | Fines for failing to settle a trade on time (EU Regulation). | | `dependent_support_payment` | Dependent Support. | Paying to support a child or dependent (non-gov). | | `retail_payment` | Retail Payment. | General shopping/e-commerce purchase. | | `charges_borne_by_debtor` | Debtor Charges. | Paying fees owed by the person in debt. | ## What's next? #### [Billing Request Purpose Codes](/docs/collect-payments/scheme-guidance/billing-request-purpose-codes) Browse purpose codes for Billing Requests and PayTo. #### [ACH and PAD Consent Types](/docs/collect-payments/scheme-guidance/ach-and-pad-consent-types) Learn about consent types for ACH and PAD mandates. #### [Variable Recurring Payments](/docs/collect-payments/recurring-payments/variable-recurring-payments) Use VRP Commercial purpose codes when setting up VRP mandates. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Create mandates using the Billing Requests API. ## Components for Partners URL: https://docs.gocardless.com/docs/collect-payments/integration-types/gocardless-components/partners > How partner integrators mint session tokens and scope creditor validation when managing GoCardless Components on behalf of multiple merchant organisations. # GoCardless Components for Partners If you're integrating GoCardless Components on behalf of multiple merchant organisations rather than a single merchant integrating for itself, session tokens and creditor scoping both need extra care. Each merchant you manage is a separate GoCardless organisation, and both the session token you mint and the bootstrap data you request are scoped to exactly one organisation at a time. There are no "partner-level" credentials that reach across every merchant you manage. This guide assumes each merchant has already given you an API access token. It builds on [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) — read that first for the frontend setup and public token flow. ## 1. One access token per merchant Each merchant you manage issues you their own API access token, scoped to their organisation only — not one token that spans every merchant you manage. If you manage 5 merchants, you'll need to hold 5 access tokens, each usable only for its own organisation. Everything downstream — session tokens, creditor scoping — inherits from whichever access token you use to make the request. ## 2. Minting a session token per merchant `POST /session_tokens` mints a session token from the access token in your `Authorization` header. The token it returns is scoped to that access token's organisation only. ```json POST /session_tokens HTTP/1.1 Authorization: Bearer Content-Type: application/json { "session_tokens": { "policies": ["ui_components"] } } ``` ```json HTTP/1.1 201 Content-Type: application/json { "session_tokens": { "id": "SESH00001078YT4H", "token": "sesh_live_mdhBfRflA-uuR9ptHN8Q94HOoRqIiMx7yAbII02Q" } } ``` Before you can mint one for a merchant, your access token for that merchant needs the `ui_components` capability granted (only the `ui_components` policy is supported during Early Access). > **Warning:** > Mint a fresh session token per merchant, from that merchant's own access token, for every > checkout. A session token minted for one merchant cannot be reused for another — the bootstrap > endpoint rejects creditor IDs that don't belong to the token's organisation. > **Info:** > Session tokens are valid for 30 minutes. Look up the right access token for the merchant at the > start of each checkout rather than caching a session token across merchants or across sessions. ## 3. Creditor validation: partners vs. a single merchant A single-merchant integration usually never needs to set a creditor ID, since the organisation only has one creditor. Merchants you manage as a partner are often different: an organisation can have more than one creditor underneath it. Pass that merchant's creditor ID when you initialise the Component and the SDK scopes the checkout to that creditor for you. Do this by default for every partner-managed merchant — omitting it falls back to resolving at the organisation level, which is only safe when the merchant has a single creditor. Every creditor ID you pass must belong to the same organisation as the access token that minted the session token. ## 4. Putting it all together For each checkout: 1. Look up the API access token the merchant gave you for the merchant the payer is checking out with. 2. On your backend, `POST /session_tokens` with that access token to mint a session token scoped to that merchant's organisation. 3. Pass the session token to the frontend and initialise the Component with it, along with that merchant's creditor ID (or omit it for the default organisation-level creditor resolution). 4. Mount the Billing Component as normal — see [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components#2-implementation) for the frontend setup. ## What's next? #### [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) Core setup and frontend implementation for GoCardless Components. #### [Remember Me Components](/docs/collect-payments/integration-types/gocardless-components/remember-me) Recognise returning customers and save new customer details for faster future payments. ## Remember Me Components URL: https://docs.gocardless.com/docs/collect-payments/integration-types/gocardless-components/remember-me > Integrate Remember Me components into your checkout flow to recognise returning customers and save new customer details for faster future payments. # GoCardless Remember Me Components GoCardless Components is a JavaScript component library aimed at providing GoCardless integrators with customisable functionality for creating checkout flows without the need to build their own from scratch using the API. This document explains how to integrate the Remember Me components into your checkout flow. ## 1. Prerequisites ### 1.1. Billing Request Setup Remember Me components require a valid Billing Request ID to function. Ensure you can: 1. Create billing requests via the GoCardless API 2. Pass billing request IDs to your frontend 3. Fulfil billing requests from your backend If you haven't created a billing request yet, see the [GoCardless API Documentation](/docs/api-reference/billing-request). ### 1.2. Requirements Before implementing Remember Me components, ensure you have: 1. **Active GoCardless Account** with the GoCardless Components upgrade activated - Contact your implementation manager to enable this 2. **Public Token** with appropriate scopes To generate a public token via the dashboard, go to [https://manage-sandbox.gocardless.com/developers/public-tokens](https://manage-sandbox.gocardless.com/developers/public-tokens) and do the following: 1. Select **Create public token** 2. Enter a **Name** to identify this token 3. Provide the **Domain** where you will be using the GoCardless Component 4. Tick the `ui_components_remember_me` scope 5. Click **Create** 3. **Billing Request** implemented - Must have an existing billing request created ## 2. Components ### 2.1. Component Types GoCardless provides two Remember Me components: #### ReturnFlow Component Used at the start of checkout to recognise and verify returning customers who have previously saved their details with GoCardless. - **Use when:** Customer enters checkout flow - **Purpose:** Recognise customers via email and complete verification to pre-fill payment details - **Recommended location:** Top of checkout page, before any form fields ![ReturnFlow Component](/images/components/remember-me-return-flow.png) #### Signup Component Used during checkout to allow new customers to opt-in to saving their details for future use. - **Use when:** New customer completes payment or at any point in the checkout flow as long as the billing request has been created or started. - **Purpose:** Saves customer details for a faster checkout experience in the future - **Recommended location:** Payment confirmation page, below success message or inline during checkout as opt-in checkbox ![Signup Component](/images/components/remember-me-signup.png) ## 3. Installation ### 3.1. Add GoCardless Components Library #### React Dependency The GoCardless Components library requires React as a global variable: ```html ``` #### GoCardless Components Add the latest version of the GoCardless Components library: ```html ``` To patch the styling of the Signup component of the GoCardless Components library, link the compiled CSS globally in the build: ```html ``` Using the latest version of the GoCardless Components library is advised during the development and testing phases of the integration. However, for go-live, it is recommended to use a specific version of the GoCardless Components library: ```html ``` ```html ``` ### 3.2. TypeScript Configuration If you're using TypeScript, add global type definitions to enable proper type checking for the GoCardless Components library. #### Create Global Type Definitions Create a file at `src/types/global.d.ts` with the following content: ```typescript interface RememberMeReturnConfigurationParams { publicToken: string; environment: string; scheme: string; enableAnalytics?: boolean; appearance?: { variables?: Record; }; } interface MountableComponent { mount: () => void; unmount: () => void; } interface LoadConfigResponse { success: boolean; error?: Error; } enum Environment { Sandbox = "sandbox", Live = "live", } enum Scheme { Bacs = "bacs", } interface RememberMeSignupProps { billingRequestId: string; email: string; onError?: (error: Error) => void; onSuccess?: (result: { email: string; phoneNumber?: null | string }) => void; } interface RecognisedCustomerData { email: string; phoneNumber?: string; customerId: string; bankAccountId: string; } interface CustomerRecognitionResult { recognised: boolean; customerData?: RecognisedCustomerData; } interface VerificationResult { success: boolean; customerId?: string; billingRequest?: BillingRequestResource; error?: Error; } enum VerificationExitPoint { UserClosed = "user_closed", VerificationFailed = "verification_failed", VerificationSuccess = "verification_success", } export interface RememberMeReturnFlowProps { billingRequestId: string; defaultEmail?: string; onChange?: (email: string) => void; onCustomerRecognitionCheck?: (result: CustomerRecognitionResult) => void; onError?: (error: Error) => void; onVerificationAttempt?: (result: VerificationResult) => void; onVerificationExit?: (exitPoint: VerificationExitPoint) => void; } declare global { interface Window { GcComponents: { createRememberMeReturnFlowComponent: ( selector: string, options: RememberMeReturnFlowProps, ) => MountableComponent; createRememberMeSignupComponent: ( selector: string, options: RememberMeSignupProps, ) => MountableComponent; createErrorComponent: (selector: string) => MountableComponent; loadConfig: (config: RememberMeReturnConfigurationParams) => Promise; Environment: typeof Environment; Scheme: typeof Scheme; }; } } export {}; ``` This provides type safety for the `window.GcComponents` global object and all callback interfaces. #### Update tsconfig.json Ensure your `tsconfig.json` includes the types directory: ```json { "compilerOptions": { "typeRoots": ["./node_modules/@types", "./src/types"] }, "include": ["src"] } ``` ### 3.3. Using the useGoCardlessComponents Hook (React) For React applications, create a custom hook to detect when the GoCardless Components library has loaded: #### Create the Hook Create a file at `src/hooks/useGoCardlessComponents.ts`: ```typescript export function useGoCardlessComponents() { const [isLoaded, setIsLoaded] = useState(false); const [error, setError] = useState(null); useEffect(() => { let attempts = 0; const maxAttempts = 10; const checkComponentsLoaded = () => { attempts++; // Check if the global GcComponents library is available if (window.GcComponents) { setIsLoaded(true); return; } if (attempts >= maxAttempts) { const err = new Error( "GoCardless Components failed to load. Please check your internet connection.", ); setError(err); return; } // Retry after 100ms setTimeout(checkComponentsLoaded, 100); }; checkComponentsLoaded(); }, []); return { isLoaded, error }; } ``` #### Using the Hook ```typescript const CheckoutPage = () => { const { isLoaded, error } = useGoCardlessComponents(); if (error) { return
Error: {error.message}
; } if (!isLoaded) { return
Loading GoCardless Components...
; } // Proceed with rendering components return
{/* Your checkout form */}
; }; ``` ### 3.4. Configure Components Load your configuration before creating components: ```typescript const config = { publicToken: YOUR_PUBLIC_TOKEN, environment: GcComponents.Environment.Sandbox, // or Environment.Live scheme: GcComponents.Scheme.Bacs, enableAnalytics: true, // Optional: defaults to true }; GcComponents.loadConfig(config); ``` #### Configuration Options | Property | Description | Required | | ----------------- | ------------------------------------------------------------ | -------- | | `publicToken` | Your public token with the `ui_components_remember_me` scope | Yes | | `environment` | `Sandbox` or `Live` | Yes | | `scheme` | Payment scheme (currently only Bacs supported) | Yes | | `enableAnalytics` | Enable usage analytics (default: `true`) | No | ### 3.5. Select where to mount GoCardless Components When creating a GC Component, you need to specify where on your webpage it will be mounted. Create a `` in your app in the place you want the GC Component to be displayed and give it an intuitive identifier (i.e. `gc-billing-return-flow`), to select when creating a component. Example: ```html
``` ## 4. Frontend Implementation ### 4.1. Implementing ReturnFlow for Returning Customers The ReturnFlow component should be placed at the beginning of your checkout flow to recognise and verify returning customers. #### Basic Implementation ```typescript const CheckoutPage = () => { const [billingRequestId] = useState('BR123456'); // From your backend const [isVerified, setIsVerified] = useState(false); const handleCustomerRecognised = (result) => { if (result.recognised) { console.log('Customer recognised', result.customerData); // Customer found - they will be prompted for verification } else { console.log('Customer not recognised - show standard checkout'); // Show your normal checkout form } }; const handleVerificationSuccess = (result) => { if (result.success) { console.log('Verification complete'); setIsVerified(true); // Pre-fill customer details from result.billingRequest // Navigate to confirmation page } }; const handleVerificationExit = (exitPoint) => { if (exitPoint === 'user_closed') { // User cancelled - show manual entry option console.log('User cancelled verification'); } else if (exitPoint === 'verification_failed') { // Verification failed - offer retry or manual entry console.log('Verification failed'); } }; const handleError = (error) => { console.error('Remember Me error:', error); // Fallback to standard checkout }; return (

Checkout

{/* Show manual checkout form if needed */} {!isVerified && }
); }; ``` #### ReturnFlow Props | Prop | Type | Required | Description | | ---------------------------- | -------- | -------- | ------------------------------------------------------------------ | | `billingRequestId` | string | Yes | Unique billing request ID for this transaction | | `defaultEmail` | string | No | Pre-populate email field (e.g., from logged-in session) | | `onCustomerRecognitionCheck` | function | No | Called when customer recognition check completes | | `onVerificationAttempt` | function | No | Called when verification is attempted | | `onVerificationExit` | function | No | Called when user exits verification flow | | `onError` | function | No | Global error handler | | `onChange` | function | No | Handles the input change when the payer enters their email address | #### Callback Data Structures **onCustomerRecognitionCheck:** ```typescript { recognised: boolean, customerData?: { customerId: string, bankAccountId: string, email: string, phoneNumber?: string } } ``` **onVerificationAttempt:** ```typescript { success: boolean, customerId?: string, billingRequest?: BillingRequestResource, error?: Error } ``` **onVerificationExit:** ```typescript // exitPoint values: "user_closed" | "verification_failed" | "verification_success"; ``` ### 4.2. Using ReturnFlow Inside a Form The ReturnFlow component can be embedded directly inside your checkout form to provide a seamless experience. The component replaces the email input field and handles customer recognition and verification. #### Implementation Example ```typescript const CheckoutForm = ({ billingRequestId, onCustomerRecognitionCheck, onVerificationAttempt, onVerificationExit, onError, }) => { const { isLoaded } = useGoCardlessComponents(); const componentInstance = useRef(null); const [formData, setFormData] = useState({ email: '', firstName: '', lastName: '', // ... other fields }); // Mount the RememberMeReturnFlow component useEffect(() => { if (!isLoaded || !billingRequestId || !window.GcComponents) return; const config = { publicToken: YOUR_PUBLIC_TOKEN, environment: GcComponents.Environment.Sandbox, scheme: GcComponents.Scheme.Bacs, }; const mountComponent = async () => { const { success } = await window.GcComponents.loadConfig(config); if (success) { const options = { billingRequestId, defaultEmail: formData.email, // Sync email changes to form state onChange: (email) => { setFormData((prev) => ({ ...prev, email })); }, onCustomerRecognitionCheck, onVerificationAttempt, onVerificationExit, onError, }; componentInstance.current = window.GcComponents.createRememberMeReturnFlowComponent( '#gc-remember-me-return-flow', options ); componentInstance.current.mount(); } }; mountComponent(); // Cleanup on unmount return () => { if (componentInstance.current) { componentInstance.current.unmount(); } }; }, [isLoaded, billingRequestId]); const handleSubmit = (e) => { e.preventDefault(); // Submit form data }; return (

Checkout

{/* ReturnFlow component mounts here and replaces email input */}
setFormData({ ...formData, firstName: e.target.value })} />
setFormData({ ...formData, lastName: e.target.value })} />
{/* Additional form fields */}
); }; ``` #### Key Points - The ReturnFlow component replaces the email input field in your form - Use the `onChange` callback to sync the email value to your form state - Mount the component in a dedicated `` with a unique ID - The component handles email recognition and verification automatically - After verification, the customer's email is available in the `onVerificationAttempt` callback ### 4.3. Auto-filling Form Inputs After Verification When a returning customer successfully verifies their identity, you should auto-fill the form fields with their saved information from the billing request. #### Extracting Customer Data The `onVerificationAttempt` callback receives a `VerificationResult` object containing the billing request with customer data: ```typescript const handleVerificationSuccess = (result: VerificationResult) => { if (result.success && result.billingRequest) { const { resources } = result.billingRequest; const customer = resources?.customer; const billingDetail = resources?.customer_billing_detail; const bankAccount = resources?.customer_bank_account; // Extract and parse customer data if (customer && billingDetail) { // Parse address line 1 to extract house number and street const addressLine1 = billingDetail.address_line1 || ""; const addressParts = addressLine1.match(/^(\S+)\s+(.+)$/); const customerData = { email: customer.email, firstName: customer.given_name || "", lastName: customer.family_name || "", houseNumber: addressParts?.[1] || "", flatNumber: billingDetail.address_line2 || addressLine1, streetName: addressParts?.[2] || addressLine1, townCity: billingDetail.city || "", postcode: billingDetail.postal_code || "", county: billingDetail.region || "", }; // Update form state with customer data setFormData(customerData); } // Store masked bank account for display if (bankAccount) { setMaskedBankAccount(bankAccount); } // Mark customer as verified setIsVerified(true); } }; ``` #### Updating Form Inputs Make sure your form inputs are controlled components that respond to state changes: ```typescript // Use useEffect to update form data when verification completes useEffect(() => { if (verifiedCustomerData) { setFormData((prev) => ({ ...prev, ...verifiedCustomerData, })); } }, [verifiedCustomerData]); // Form inputs automatically reflect the updated state ``` #### Displaying Saved Bank Account For verified customers with saved bank accounts, display the masked account details: ```typescript {maskedBankAccount ? (

Account Holder: {maskedBankAccount.account_holder_name}

Account Number: ****{maskedBankAccount.account_number_ending}

{maskedBankAccount.bank_name && (

Bank: {maskedBankAccount.bank_name}

)}
) : ( // Show manual bank account input fields
{/* Account number, sort code, etc. */}
)} ``` ### 4.4. Implementing Signup for New Customers The Signup component should be shown to new customers during the flow or after successful payment to allow them to opt-in to Remember Me. #### Basic Implementation ```typescript const PaymentConfirmationPage = () => { const [billingRequestId] = useState('BR123456'); const [customerEmail] = useState('customer@example.com'); const [signupComplete, setSignupComplete] = useState(false); const handleSignupSuccess = (result) => { console.log('Customer enrolled in Remember Me:', result); setSignupComplete(true); // Optional: Track analytics // analytics.track('remember_me_enrolled', { customerId: result.id }); }; const handleSignupError = (error) => { console.error('Signup failed:', error); // Optional: Show user-friendly message // Don't block user from proceeding if signup fails }; return (

Payment Successful!

Thank you for your payment.

{!signupComplete && ( )} {signupComplete && (

Your details have been saved for faster checkout next time

)}
); }; ``` #### Signup Props | Prop | Type | Required | Description | | ------------------ | -------- | -------- | --------------------------------------------------- | | `billingRequestId` | string | Yes | Billing request ID for this transaction | | `email` | string | Yes | Customer's email address (already validated) | | `onSuccess` | function | No | Called when customer details are successfully saved | | `onError` | function | No | Called if enrollment fails | #### Callback Data Structures **onSuccess:** ```typescript { email: string; phoneNumber: string; } ``` ## 5. Customisation ### 5.1. Theming Both components use the GoCardless theme by default. The theme automatically adapts to create a cohesive experience. The GC Component can be customised to fit the UI of your page. This is done through the optional appearance parameter provided in the configuration step. Example: ```javascript const appearanceVariables = { variables: { backgroundColor: "#bfe6f2", inputBorderRadius: "0px", wrapperBorderRadius: "0", textFontFamily: "Georgia, serif", }, }; const config = { publicToken: YOUR_PUBLIC_TOKEN, environment: Environment.Sandbox, scheme: GcComponents.Scheme.Bacs, appearance: appearanceVariables, }; GcComponents.loadConfig(config); ``` You can modify colours, fonts, borders, padding etc. for a variety of different on-screen elements. We recommend playing around with `backgroundColor`, `textFontSize`, `textFontFamily`, `buttonColor` and `buttonBorderRadius` to get started. You may notice that GoCardless Components come with some default styling even when no appearance variables are provided. Any appearance variables you add will be applied on top of the default styles. Full list of appearance variables and their default values: ```typescript export const defaultTheme: AppearanceVariables = { backgroundColor: "#F9F9F9", buttonBorderRadius: "32px", buttonColor: "#1C1B18", buttonHoverBackgroundColor: "#545048", buttonHoverColor: "#FAF9F7", buttonSubmitTextContent: "Set up this Direct Debit", buttonTextColor: "#FAF9F7", buttonTextFontSize: "12px", buttonTextFontWeight: FontWeight.medium, checkboxBackgroundColor: "#DFDFDF", checkboxSize: "16px", checkboxTextColor: "#1C1B18", checkboxTextFontSize: "14px", checkboxTextFontWeight: FontWeight.normal, dropdownFooterBackgroundColor: "#FaF9F7", dropdownFooterBorderColor: "#dFddda", dropdownHoverBackgroundColor: "#1C1B18", dropdownHoverTextColor: "#FFFFFF", dropdownPadding: "8px", formValidationErrorColor: "#C52F2F", formVerticalSpacing: "12px", hintTextFontSize: "12px", hintTextFontWeight: "600", inputBackgroundColor: "#FFFFFF", inputBorderColor: "#8C8579", inputBorderRadius: "4px", inputPadding: "12px", inputPlaceholderColor: "#6E685E", inputTextColor: "#1C1B18", inputTextFontWeight: FontWeight.normal, labelTextColor: "#545048", labelTextFontSize: "14px", labelTextFontWeight: FontWeight.normal, linkHoverTextColor: "#1E1751", linkTextColor: "#5949CB", linkTextFontSize: "12px", linkTextFontWeight: FontWeight.normal, loadingSpinnerColor: "#1e1a14", textColor: "#000000", textFontFamily: 'Inter, "Helvetica Neue", Helvetica, Arial, sans-serif', textFontSize: "14px", textFontWeight: FontWeight.normal, wrapperBorderRadius: "8px", wrapperMargin: "16px", }; ``` ## What's next? #### [GoCardless Components](/docs/collect-payments/integration-types/gocardless-components) Learn about the core GoCardless Components library for setting up mandates. #### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates) Learn how to collect bank account details and create mandates via the API. --- # Send Money ## Introduction to Outbound Payments URL: https://docs.gocardless.com/docs/send-money > Overview of sending money with GoCardless outbound payments. # Outbound Payments This guide provides an overview of how GoCardless handles outbound payments, covering key features, examples, and API usage to ensure you have everything you need to get started. ## What is an Outbound Payment? Outbound Payments enable merchants to send money using the GoCardless API. Why "Outbound Payments"? Unlike collection payments, where funds move from customers to merchants, the money flow for sending money is reversed — funds are transferred from the merchant's account to the recipient's account. To clearly reflect this reversed flow, we named the resource "Outbound Payment". ## Availability | Geo | Currency | Scheme | | ----- | -------- | ----------------- | | 🇬🇧 UK | GBP | `faster_payments` | ## What's next? #### [Payment Account](/docs/send-money/payment-account) Fund and manage the payment account used to send outbound payments. #### [API Request Signing](/docs/send-money/api-request-signing) Set up request signing to secure your API calls. #### [Send an Outbound Payment](/docs/send-money/send-an-outbound-payment) Add a recipient and initiate your first outbound payment. #### [Tracking Outbound Payments](/docs/send-money/tracking-outbound-payments) Monitor payment status and lifecycle events. ## API Request Signing URL: https://docs.gocardless.com/docs/send-money/api-request-signing > Sign API requests for outbound payments. # API request signing We require API Request Signing to secure your communication to the GoCardless API and to comply with the Strong Customer Authentication requirement. This section will walk you through how to: - Generate public and private keys and upload the public key to GoCardless - Build the signature base that will be used to generate the Gc-Signature header - Build and attach the Gc-Signature and Gc-Signature-Input headers and send them with your API request ## Sandbox developer bypass For ease of development (e.g. testing our endpoints with Postman or curl), it is possible to bypass request signing in the sandbox environment using the following header: ```http Gc-Signature: sig-1=:DEVELOPER: ``` ## Generate your key pair 1. We use ECDSA keys for API request signing. You must generate an ES512 key pair using the P-521 elliptic curve without a passphrase. Use the following commands in a terminal to generate your key pair: ```bash openssl ecparam -name secp521r1 -genkey -noout -out ec-secp521r1-priv-key.pem openssl ec -in ec-secp521r1-priv-key.pem -pubout > ec-secp521r1-pub-key.pem ``` 2. Securely save your private key. 3. Upload your public key to GoCardless via the dashboard. - Go to [Settings → Account settings](https://manage-sandbox.gocardless.com/company/settings). - Under "API request signing", add a new public key. ```bash cat ec-secp521r1-pub-key.pem # Copy this output and paste into the form. It should look something like: # -----BEGIN PUBLIC KEY----- # MIGbMBAGByqG..................... # ................................. # ................ # -----END PUBLIC KEY----- ``` When you've added a new public key, a corresponding request_signing_key ID (e.g. `RSK00123456789300123456789300`) is generated. You will need this for building the request signature. ## Signing the API request We follow the [RFC-9421](https://datatracker.ietf.org/doc/rfc9421/) specification for HTTP Message Signatures. 1. Create the signature base. This is a raw string containing all the components covered by the signature. It must be in the format shown in the example below. ```signature "@method": POST "@authority": api.gocardless.com "@request-target": /path?param=value "content-digest": sha256=:9AmU2hRsZnqEo2HiNTLacLN0fOs8YmDiuX4WYeYWvh0=: "content-type": application/json "content-length": 18 "@signature-params": ("@method" "@authority" "@request-target" "content-digest" "content-type" "content-length");keyid="your-public-key-identifier";created=1675688690;nonce="8IBTHwOdqNKAWeKl7plt8g==" ``` ```ruby signature_base = <<~SIGNATURE_BASE.chomp "@method": POST "@authority": api.gocardless.com "@request-target": /path?param=value "content-digest": sha256=:9AmU2hRsZnqEo2HiNTLacLN0fOs8YmDiuX4WYeYWvh0=: "content-type": application/json "content-length": 18 "@signature-params": ("@method" "@authority" "@request-target" "content-digest" "content-type" "content-length");keyid="your-public-key-identifier";created=1675688690;nonce="8IBTHwOdqNKAWeKl7plt8g==" SIGNATURE_BASE ``` ```c# var signatureBase = SignatureBase( httpMethod: "POST", host: "api.gocardless.com", requestPath: "/outbound_payments", contentDigest: "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", contentType: "application/json", contentLength: 123, keyId: "RSK00123456789300123456789300", created: DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), nonce: Guid.NewGuid().ToString()); static string SignatureParams(string keyId, string created, string nonce, bool includeContentParams) { var components = includeContentParams ? "\"@method\" \"@authority\" \"@request-target\" \"content-digest\" \"content-type\" \"content-length\"" : "\"@method\" \"@authority\" \"@request-target\""; return $"({components});keyid=\"{keyId}\";created={created};nonce=\"{nonce}\""; } static string SignatureBase( string httpMethod, string host, string requestPath, string? contentDigest, string? contentType, int? contentLength, string keyId, string created, string nonce) { var includeContentParams = !string.IsNullOrWhiteSpace(contentDigest); var lines = new List { $"\"@method\": {httpMethod}", $"\"@authority\": {host}", $"\"@request-target\": {requestPath}", }; if (includeContentParams) { lines.Add($"\"content-digest\": sha256=:{contentDigest}:"); lines.Add($"\"content-type\": {contentType}"); lines.Add($"\"content-length\": {contentLength}"); } lines.Add($"\"@signature-params\": {SignatureParams(keyId, created, nonce, includeContentParams)}"); return string.Join("\n", lines); } ``` ```typescript // Example for POST request const signatureBase = `"@method": POST "@authority": api.gocardless.com "@request-target": /path?param=value "content-digest": sha256=:9AmU2hRsZnqEo2HiNTLacLN0fOs8YmDiuX4WYeYWvh0=: "content-type": application/json "content-length": 18 "@signature-params": ("@method" "@authority" "@request-target" "content-digest" "content-type" "content-length");keyid="RSK00123456789300123456789300";created=1675688690;nonce="8IBTHwOdqNKAWeKl7plt8g=="`; // Example for GET request const signatureBaseGet = `"@method": GET "@authority": api.gocardless.com "@request-target": /path?param=value "@signature-params": ("@method" "@authority" "@request-target");keyid="RSK00123456789300123456789300";created=1675688690;nonce="8IBTHwOdqNKAWeKl7plt8g=="`; ``` **Requirements:** 1. Each line is concatenated with a **newline character (`\n`)**. 2. You must **respect the format** (e.g., respect every character like `"`, `@`, or spaces). 3. `@method`, `@authority`, and `@request-target` are **required components** in building the signature base. You can add any other signed headers you want to include into the signature base. They **must appear in the same order** as listed in `@signature-params`. For any additional signed headers, you **must pass them as HTTP headers** in the request itself. The following table describes how the signature base is built: | Key | Value | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `"@method"` | The HTTP method in uppercase, e.g. `GET` or `POST`. | | `"@authority"` | The target URI host, usually conveyed via the Host header (e.g. `api.gocardless.com`). | | `"@request-target"` | The full path including any query parameters. Query parameters must be ordered deterministically by sorting keys. | | `"content-digest"` | _Only needed if the request has a body (e.g. POST/PUT)._ SHA-256 base64-encoded hash of the body, wrapped as `sha256=:CONTENT_DIGEST:`. The body must be serialised deterministically (sorted keys) to produce a consistent digest. | | `"content-type"` | _Only needed if the request has a body._ The content type, e.g. `application/json`. | | `"content-length"` | _Only needed if the request has a body._ Size of the message body in bytes. | | `"@signature-params"` | The following signature parameters should be passed as follows and separated by semicolon: `();;` **Signature Components** In brackets — the components of the request that are included in the signature process. This would be `"@method" "@authority" "@request-target"`, followed by any additional request headers, each separated by a space. **They should appear in the order as you used to build the rest of the signature base.** **Signature Parameters** `keyid` — the identifier of your public request signing key. `created` — a Unix timestamp (e.g. 1675688690) in UTC. `nonce` — a [random unique value](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) generated for this signature as a String value. This must be a random base64-encoded string of at least 128 bits of data from a cryptographically secure random number generator. | More details on building the signature base can be found in section 2.5 of [RFC-9421](https://datatracker.ietf.org/doc/rfc9421/). 2. Sign the signature base with your private key. ```ruby private_key = OpenSSL::PKey::EC.new(your_private_key) signature = private_key.sign(OpenSSL::Digest.new("SHA512"), signature_base) ``` ```c# using var privateKeyPem = File.OpenText("ec-secp521r1-priv-key.pem"); var signature = GetSignature(privateKeyPem, signatureBase); string GetSignature(TextReader privateKeyPem, string message) { var keys = (AsymmetricCipherKeyPair)new PemReader(privateKeyPem).ReadObject(); var signer = SignerUtilities.GetSigner("SHA-512withECDSA"); var privateKey = keys.Private; signer.Init(true, privateKey); var messageBytes = GetMessageBytes(message); signer.BlockUpdate(messageBytes, 0, messageBytes.Length); return signer.GenerateSignature(); } ``` ```typescript import * as crypto from "node:crypto"; import { Buffer } from "node:buffer"; import * as fs from "node:fs"; // Read in signature file const privateKeyPem = fs.readFileSync("ec-secp521r1-priv-key.pem", "utf-8"); // Create a private key object const privateKey = crypto.createPrivateKey({ key: privateKeyPem, format: "pem", }); // Prepare the data for signing const dataBuffer = Buffer.from(signatureBase, "utf8"); // Generate the signature const sign = crypto.createSign("SHA512"); sign.update(dataBuffer); sign.end(); const signature = sign.sign(privateKey, "base64"); console.log("Signature:", signature); ``` 3. Encode the signature in base64. ```ruby encoded_signature = Base64.strict_encode64(signature) ``` ```c# const signatureStr = Convert.ToBase64String(signature); ``` 4. Set the `Gc-Signature` and `Gc-Signature-Input` HTTP headers. **Requirements:** - `Gc-Signature` is the base64 encoded signature. It must be in the format `Gc-Signature: sig-1=::` where `sig-1` identifies the signature and the value is wrapped in colons. - `Gc-Signature-Input` is the same string as `@signature-params` used in building the signature base. It must be in the format `sig-1=`. ```http Gc-Signature-Input: sig-1=("@method" "@authority" "@request-target" "content-digest" "content-type" "content-length");keyid="your-public-key-identifier";created=1675688690;nonce="8IBTHwOdqNKAWeKl7plt8g==" Gc-Signature: sig-1=:LjbtqUbfmvjj5C5kr1Ugj4PmLYvx9wVjZvD9GsTT4F7GrcQ\ EdJzgI9qHxICagShLRiLMlAJjtq6N4CDfKtjvuJyE5qH7KT8UCMkSowOB4+ECxCmT\ 8rtAmj/0PIXxi0A0nxKyB09RNrCQibbUjsLS/2YyFYXEu4TRJQzRw1rLEuEfY17SA\ RYhpTlaqwZVtR8NV7+4UKkjqpcAoFqWFQh62s7Cl+H2fjBSpqfZUJcsIk4N6wiKYd\ 4je2U/lankenQ99PZfB4jY3I5rSV2DSBVkSFsURIjYErOs0tFTQosMTAoxk//0RoK\ UqiYY8Bh0aaUEb0rQl3/XaVe4bXTugEjHSw==: ``` 5. Send your request with the attached headers. If making a request with a payload, the payload sent must have the same structure as used to generate the `content-digest` to ensure they match during verification. ## Code Example Example methods for building the signature headers: ```ruby module SignatureHelper ### Build Signature Base def self.signature_base(http_method, host, request_uri, content_digest, content_type, content_length, key_id, created, nonce) signature_base = <<~SIGBASE "@method": #{http_method} "@authority": #{host} "@request-target": #{request_uri} "content-digest": sha256=:#{content_digest}: "content-type": #{content_type} "content-length": #{content_length} "@signature-params": #{signature_params(key_id, created, nonce)} SIGBASE signature_base.strip end ### Build Signature Params def self.signature_params(key_id, created, nonce) '("@method" "@authority" "@request-target" "content-digest" "content-type" "content-length");keyid="%s";created=%d;nonce="%s"' % [key_id, created, nonce] end ### Sign and return base64 encoded signature for `Gc-Signature` header def self.signature_header(private_key_pem, signature_base) private_key = OpenSSL::PKey::EC.new(private_key_pem) signature = private_key.sign(OpenSSL::Digest.new("SHA512"), signature_base) signature = Base64.strict_encode64(signature) "sig-1=:#{signature}:" end ### Return value for `Gc-Signature-Input` header def self.signature_input_header(key_id, created, nonce) "sig-1=#{signature_params(key_id, created, nonce)}" end ### Sort query parameters to be used in request URL and @request-target def self.order_query_params(original_url) return original_url if original_url.nil? || original_url.empty? uri = URI.parse(original_url) return original_url unless uri.query query_params = URI.decode_www_form(uri.query).sort uri.query = URI.encode_www_form(query_params) uri.to_s end ### Sort request body to be used in request and Content-Digest def self.order_request_body(request_body) json_string = JSON.generate(sort_hash(request_body)) json_string end def self.sort_hash(hash) # Recursively sort the hash and its nested hashes hash.each_with_object({}) do |(key, value), sorted_hash| sorted_key = key.to_s # Convert key to string sorted_value = value.is_a?(Hash) ? sort_hash(value) : value sorted_hash[sorted_key] = sorted_value end.sort.to_h # Sort the hash by keys and convert back to a hash end ### Calculate Content-Digest def self.content_digest(request_body) digest = OpenSSL::Digest.new("SHA256").digest(request_body) Base64.strict_encode64(digest) end end ``` ```c# using System.Security.Cryptography; using System.Text; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Security; class SignatureHelper { public SignatureHelper( TextReader privateKeyPem, string httpMethod, string host, string requestPath, string keyId, string? contentDigest = null, int? contentLength = null, string? contentType = "application/json", string? created = null, string? nonce = null) { nonce ??= Guid.NewGuid().ToString(); // Notice we expect seconds since epoch (not milliseconds/nanoseconds) to UTC now. created ??= DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); var sigBase = SignatureBase(httpMethod, host, requestPath, contentDigest, contentType, contentLength, keyId, created, nonce); var signature = GetSignature(privateKeyPem, sigBase); this.GcSignature = SignatureHeader(signature); this.GcSignatureInput = SignatureInputHeader(keyId, created, nonce, includeContentParams: contentDigest != null); } public string GcSignature { get; private set; } public string GcSignatureInput { get; private set; } private void verifySignature(TextReader publicKeyPem, string signature, string signatureBase) { if (publicKeyPem == null) return; var signatureBytes = Convert.FromBase64String(signature); var publicKey = (AsymmetricKeyParameter)new PemReader(publicKeyPem).ReadObject(); var verifier = SignerUtilities.GetSigner("SHA-512withECDSA"); verifier.Init(false, publicKey); var messageBytes = GetMessageBytes(signatureBase); verifier.BlockUpdate(messageBytes, 0, messageBytes.Length); if (!verifier.VerifySignature(signatureBytes)) { throw new Exception("Signature verification failed"); } } public static string HashWithSHA256(string value) { var byteArray = SHA256.HashData(Encoding.UTF8.GetBytes(value)); return Convert.ToBase64String(byteArray); } private string SignatureHeader(string signature) { return $"sig-1=:{signature}:"; } private string SignatureInputHeader(string keyId, string created, string nonce, bool includeContentParams) => $"sig-1={SignatureParams(keyId, created, nonce, includeContentParams)}"; private string SignatureBase( string httpMethod, string host, string requestPath, string? contentDigest, string? contentType, int? contentLength, string keyId, string created, string nonce) => ($"\"@method\": {httpMethod}\n" + $"\"@authority\": {host}\n" + $"\"@request-target\": {requestPath}\n" + (string.IsNullOrWhiteSpace(contentDigest) ? "" : $"\"content-digest\": sha256=:{contentDigest}:\n" + $"\"content-type\": {contentType}\n" + $"\"content-length\": {contentLength}\n") + $"\"@signature-params\": {SignatureParams(keyId, created, nonce, includeContentParams: contentDigest != null)}") .Trim(); private string SignatureParams(string keyId, string created, string nonce, bool includeContentParams) { return @$"(""@method"" ""@authority"" ""@request-target""" + (includeContentParams ? @" ""content-digest"" ""content-type"" ""content-length""" : "") + @$");keyid=""{keyId}"";created={created};nonce=""{nonce}"""; } private string GetSignature(TextReader privateKeyPem, string message) { var keys = (AsymmetricCipherKeyPair)new PemReader(privateKeyPem).ReadObject(); var signer = SignerUtilities.GetSigner("SHA-512withECDSA"); var privateKey = keys.Private; signer.Init(true, privateKey); var messageBytes = GetMessageBytes(message); signer.BlockUpdate(messageBytes, 0, messageBytes.Length); var signature = signer.GenerateSignature(); return Convert.ToBase64String(signature); } private byte[] GetMessageBytes(string message) => Encoding.UTF8.GetBytes(message); } ``` ```typescript import { GoCardlessClient } from "gocardless-nodejs/client" import { v4 as uuid } from 'uuid'; import * as fs from 'node:fs'; import * as crypto from 'node:crypto'; import { Buffer } from 'node:buffer'; class SignatureHelper { public constructor( privateKeyPem: string, httpMethod: "GET" | "PUT" | "POST" | "PATCH" | "DELETE" | string, host: string, requestPath: string, keyId: string, contentDigest?: string, contentLength?: number, created?: string, nonce?: string, publicKeyPem?: string, // debug contentType: string = "application/json", ) { nonce = nonce || uuid().toString(); // Notice we expect seconds since epoch (not milliseconds/nanoseconds) to UTC now. created = created || Math.floor(Date.now() / 1000).toString(); const sigBase = this.getSignatureBase(httpMethod, host, requestPath, keyId, created, nonce, contentDigest, contentType, contentLength); console.log("Signature Base:", sigBase); const sig = this.getSignature(privateKeyPem, sigBase, publicKeyPem); this._gcSignature = this.getSignatureHeader(sig); this._gcSignatureInput = this.getSignatureInputHeader(keyId, created, nonce, contentDigest != null); } private _gcSignature: string; private _gcSignatureInput: string; public getGcSignature(): string { return this._gcSignature; } public getGcSignatureInput(): string { return this._gcSignatureInput; } public static getRequestBody(client: GoCardlessClient, method: 'put' | 'post', requestParameters: any, payloadKey: string): string | undefined { // @ts-ignore return JSON.stringify(client._api.getRequestBody(method, requestParameters, payloadKey)); } public static getSha256DigestHeader(digest: string): string { return `sha256=:${digest}:`; } public static getSha256Digest( content: string, algorithm: string = 'sha256', encoding: crypto.BinaryToTextEncoding = 'base64' ): string { try { if (typeof content !== 'string') { throw new TypeError('Input content must be a string.'); } const hash = crypto.createHash(algorithm); hash.update(content, 'utf8'); const digest = hash.digest(encoding); return digest; } catch (error) { console.error(`Error generating content digest using ${algorithm}:`, error); throw error; } } private getSignatureBase(httpMethod: string, host: string, requestPath: string, keyId: string, created: string, nonce: string, contentDigest?: string, contentType?: string, contentLength?: number): string { return (`"@method": ${httpMethod}\n` + `"@authority": ${host}\n` + `"@request-target": ${requestPath}\n` + (!contentDigest ? "" : `"content-digest": sha256=:${contentDigest}:\n` + `"content-type": ${contentType}\n` + `"content-length": ${contentLength}\n`) + `"@signature-params": ${this.getSignatureParams(keyId, created, nonce, contentDigest != null)}`) .trim(); } private getSignatureHeader(signature: string): string { return `sig-1=:${signature}:`; } private getSignatureInputHeader(keyId: string, created: string, nonce: string, includeContentParams: boolean): string { return `sig-1=${this.getSignatureParams(keyId, created, nonce, includeContentParams)}`; } private getSignatureParams(keyId: string, created: string, nonce: string, includeContentParams: boolean): string { return `("@method" "@authority" "@request-target"` + (includeContentParams ? ` "content-digest" "content-type" "content-length"` : "") + `);keyid="${keyId}";created=${created};nonce="${nonce}"`; } private getSignature(privateKeyPem: string, message: string, publicKeyPem?: string): string { const sig = this.signStringSecp521r1(privateKeyPem, message); if (publicKeyPem) { const isValid = this.verifySignatureSecp521r1(publicKeyPem, message, sig); if (!isValid) { throw new Error("Signature verification failed"); } } return sig; } private signStringSecp521r1(privateKeyPem: string, dataToSign: string): string { try { const privateKey = crypto.createPrivateKey({ key: privateKeyPem, format: 'pem', }); const dataBuffer = Buffer.from(dataToSign, 'utf8'); const sign = crypto.createSign('SHA512'); sign.update(dataBuffer); sign.end(); const signature = sign.sign(privateKey, 'base64'); return signature; } catch (error) { console.error('Error signing string:', error); throw error; } } private verifySignatureSecp521r1(publicKeyPem: string, dataToVerify: string, signatureBase64: string): boolean { try { const publicKey = crypto.createPublicKey({ key: publicKeyPem, format: 'pem', }); const dataBuffer = Buffer.from(dataToVerify, 'utf8'); const verify = crypto.createVerify('SHA512'); verify.update(dataBuffer); verify.end(); const isValid = verify.verify(publicKey, signatureBase64, 'base64'); return isValid; } catch (error) { console.error('Error verifying signature with public key PEM:', error); return false; } } } ``` You can then use this code to generate the HTTP Signature headers and attach them to your request: ```ruby def make_request(request_body, request_uri, private_key) sorted_request_body = SignatureHelper.order_request_body(request_body) content_digest = SignatureHelper.content_digest(sorted_request_body) content_length = sorted_request_body.bytesize content_type = "application/json" sorted_request_uri = SignatureHelper.order_query_params(request_uri) created = Time.now.to_i nonce = SecureRandom.alphanumeric(16) key_id = "YOUR_REQUEST_SIGNING_KEY_ID" signature_base = SignatureHelper.signature_base("POST", "api-sandbox.gocardless.com", sorted_request_uri, content_digest, content_type, content_length, key_id, created, nonce) signature_header = SignatureHelper.signature_header(private_key, signature_base) signature_input_header = SignatureHelper.signature_input_header(key_id, created, nonce) # Make the request attaching the required headers end ``` ```c# using GoCardless; using GoCardless.Services; // Init the GoCardless .NET client var accessToken = "live_XXXXXXXXXXXXXX"; // your API access token var gocardless = GoCardlessClient.Create(accessToken, GoCardlessClient.Environment.SANDBOX); // Set up request signing // Provide the actual path to your file, or load the pem text into a TextReader from memory using var privateKeyPem = File.OpenText("ec-secp521r1-priv-key.pem"); // You can get the public key from the dashboard once you upload the public certificate string keyId = "RSK0000000000000000000"; // This request action will sign every request made by the client, and attach the right headers. var signApiRequest = new Action(request => { var requestBody = request.Content?.ToString(); var contentDigest = string.IsNullOrWhiteSpace(requestBody) ? null : SignatureHelper.HashWithSHA256(requestBody); var contentLength = requestBody?.Length; var requestUri = request.RequestUri ?? throw new InvalidOperationException("Request URI is null"); var signatureHelper = new SignatureHelper( privateKeyPem: privateKeyPem, httpMethod: request.Method.ToString(), host: requestUri.Host, requestPath: requestUri.PathAndQuery, keyId: keyId, contentDigest: contentDigest, contentLength: contentLength ); request.Headers.Add("Gc-Signature", signatureHelper.GcSignature); request.Headers.Add("Gc-Signature-Input", signatureHelper.GcSignatureInput); if (contentDigest != null) { request.Headers.Add("Content-Digest", contentDigest); } }); var requestSettings = new GoCardless.Internals.RequestSettings { CustomiseRequestMessage = signApiRequest }; // Get an outbound payment by ID var outboundPayment = await gocardless.OutboundPayments.GetAsync("OUTXXXXXXXXXXXXXXX", null, requestSettings); ``` ```typescript import { Environments } from "gocardless-nodejs/constants"; import { GoCardlessClient } from "gocardless-nodejs/client" import { v4 as uuid } from 'uuid'; import * as fs from 'node:fs'; import { SignatureHelper } from "."; async function main() { const token = ""; const client = new GoCardlessClient(token, Environments.Live, {}); const privateKeyPem = fs.readFileSync("ec-secp521r1-priv-key.pem", 'utf-8') // @ts-ignore const baseUrl = client._api._baseUrl; const host = new URL(baseUrl).host; const keyId = ""; // Example POST request const postRequestPath = `/outbound_payments`; const requestParams = { amount: 100, scheme: "faster_payments", links: { recipient_bank_account: "BA0003GXWZ71HA", } }; const requestBody = SignatureHelper.getRequestBody(client, "post", requestParams, 'outbound_payments')!; const digest = SignatureHelper.getSha256Digest(requestBody); const contentLength = Buffer.byteLength(requestBody, 'utf8'); const sigHelperPost = new SignatureHelper( privateKeyPem, "POST", host, postRequestPath, keyId, digest, contentLength, ); const obp = await client.outboundPayments.create(requestParams, uuid(), { "Gc-Signature": sigHelperPost.getGcSignature(), "Gc-Signature-Input": sigHelperPost.getGcSignatureInput(), "Content-Digest": SignatureHelper.getSha256DigestHeader(digest), }); console.log(obp); // Example GET request const id = obp.id const getRequestPath = `/outbound_payments/${id}`; const sigHelperGet = new SignatureHelper( privateKeyPem, "GET", host, getRequestPath, keyId, ) const updated_obp = await client.outboundPayments.find(id, { "Gc-Signature": sigHelperGet.getGcSignature(), "Gc-Signature-Input": sigHelperGet.getGcSignatureInput(), }) console.log(updated_obp); } main().catch(error => { console.error("Unhandled error in main function:", error); }); ``` ## API Response API requests that are correctly signed will be processed normally. If the signature is invalid, the API will return **401 Unauthorized**. ## Test your request signing To test whether you are correctly building request signatures, make a POST request to the `/test-signature` endpoint. It will validate the `Gc-Signature` and `Gc-Signature-Input` headers and return **204 No Content** if valid. No further validation is performed on any request body passed. ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Content-Digest: sha256=:dg0ak4ae6PgXhyxkn0FYx0th5QxzaDabkM2wBtufB2g=:" \ -H "Content-Length: 16" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ -H "Gc-Signature: sig-1=:${SIGNATURE}:" \ -H "Gc-Signature-Input: sig-1=(\"@method\" \"@authority\" \"@request-target\" \"content-digest\" \"content-type\" \"content-length\");keyid=\"${KEY_ID}\";created=${created};nonce=\"${nonce}\"" \ "https://api.gocardless.com/test_signature" \ -d @- << EOF { "foo": "bar" } EOF ``` ## What's next? #### [Send an Outbound Payment](/docs/send-money/send-an-outbound-payment) Add a recipient and initiate your first outbound payment using signed requests. #### [Strong Customer Authentication](/docs/send-money/strong-customer-authentication) Learn how SCA works alongside request signing for outbound payments. ## Bank Account Holder Verification URL: https://docs.gocardless.com/docs/send-money/bank-account-holder-verification > Verify bank account holder details before sending payments. # Bank Account Holder Verification As part of our compliance process, we perform bank account holder verification checks to reduce the risk of misdirected payments. These checks are **mandatory** and should be run for every outbound payment. While the checks themselves cannot be skipped, you remain in control of whether an outbound payment proceeds. Payments with negative verification results can still be submitted, as long as you explicitly approve them (see [the approval process](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment) for more details). Our role is to provide enough information for you to make an informed decision in these scenarios — whether to proceed or cancel. This guide explains the different types of bank account holder verification and how to interpret the results. ## Confirmation of Payee (CoP) **Confirmation of Payee (CoP)** is the bank account holder verification check used for UK domestic payments. It helps confirm that the recipient's name matches their bank account details, providing greater confidence that payments are sent to the intended recipient. For more information about the service, refer to [Pay.UK](https://www.wearepay.uk/what-we-do/overlay-services/confirmation-of-payee/). ## How to understand the verification results Once the verification checks are complete, the results are shown on the approval screen. If you are building your own integration, you can also access these results in the outbound payment response, under the `verifications` object. Within this object, the `recipient_bank_account_holder_verification` field indicates whether the recipient's account holder name matches their bank account details. It returns one of the following values: 1. `full_match` - the account name exactly matches the details provided. 2. `partial_match` - the account name is similar but does not match to the details provided. 3. `no_match` - the provided name does not match the account details. 4. `unable_to_match` - the verification could not be performed due to recipient bank issues or technical issues. If the result is a partial match, we will also provide the `actual_account_name` so you can decide if you need to correct the recipient's bank account details. ## Performing verification checks before initiating a payment If you want to retrieve bank account holder verification results before creating an outbound payment, you can run the verification check in advance. Running these preliminary checks can reduce the time required to initiate the payment. Use [Create a Bank Account Holder Verification](/docs/api-reference/bank-account-holder-verification#create-a-bank-account-holder-verification) to initiate the check, then poll for the result using [Get a Bank Account Holder Verification](/docs/api-reference/bank-account-holder-verification#get-a-bank-account-holder-verification). Once the verification is complete, you can include it in the `links` object when [creating an outbound payment](/docs/api-reference/outbound-payment#create-an-outbound-payment). ## Verifications for pooled accounts A pooled account is a single bank account that holds funds on behalf of multiple individuals. Because the sort code and account number alone identify the pooled account itself rather than any individual member within it, an additional account reference (or "roll number") is required to identify the correct sub-account. If the destination account is a pooled account, pass the roll number using the `reference` attribute when you call [Create a Bank Account Holder Verification](/docs/api-reference/bank-account-holder-verification#create-a-bank-account-holder-verification). If you don't provide a roll number when verifying a pooled account, the verification result will return `unable_to_match`. #### Creating an outbound payment When you later create an outbound payment using a verification that included a reference, you must supply the same reference on the payment. This is required because: - If a reference was needed to identify the individual for the verification check, the same reference is needed to route the payment to that individual within the pooled account. - Matching references confirm that the verified account holder and the payment destination are the same person. If the reference on the outbound payment doesn't match the reference used on the verification, the API returns a mismatch error and the payment isn't created. ## What's next? #### [Approve an outbound payment](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment) Review verification results and approve the payment to send it. #### [Tracking Outbound Payments](/docs/send-money/tracking-outbound-payments) Monitor payment status and understand the full payment lifecycle. ## Payment Account URL: https://docs.gocardless.com/docs/send-money/payment-account > Fund your payment account for outbound payments. # Payment Account ## Your Payment Account As part of the onboarding process for this feature, we will create a Payment Account for your organisation to fund the payments you wish to send. You can find the details of this account on the "Account Funding" page (_Account Balance -> Manage -> Account Funding_). > **Info:** > Available funds are automatically returned to your nominated business bank account on the first > Tuesday of **January**, **April**, **July**, and **October** to comply with regulatory > requirements. You'll receive a reminder in advance, giving you time to create any payment > instructions as needed. ## How to fund your Payment Account To comply with FinCrime regulations, any top-ups to your Payment Account must be made from your nominated (and verified) bank account, as established during the general onboarding process. We offer two funding models for your outbound payments: 1. **Direct Funding** — You receive your Payment Account details and make direct bank transfers to fund the account. If you're also collecting payments with GoCardless, outbound payments and collection payouts are kept separate: you manage the funding of your Payment Account manually, while payouts from collections are sent directly to your business account. 2. **Funding from Collections** — We redirect your collection payouts to your Payment Account. This means the money you collect from your customers can be used to fund outbound payments. However, you are responsible for organising withdrawals to your nominated business bank account, which can be done using the endpoint we provide. You can also manually fund your Payment Account if needed. By default, your organisation will use the **Direct Funding** model. If you prefer the **Funding from Collections** model, let us know and we'll configure it for you. You can also switch the funding model yourself anytime on the "Account Funding" page (_Account Balance -> Manage -> Account Funding_). The change will be applied instantly to your organisation. ## How to check your balance A balance check is essential for ensuring that your Payment Account has enough money before executing any outbound payments, helping to prevent `Insufficient Funds` errors. You can view your balance in the GoCardless dashboard by expanding "Payments" in the right-hand menu and selecting "Account Balance". It displays three key figures: - **Current Balance** — The total amount of money in your Payment Account (always zero or more). This balance reflects the amount before any scheduled payments are deducted. - **Available Funds** — The current balance minus any scheduled payments. This value can be negative if scheduled payments exceed the current account balance. - **Scheduled Payments** — The total value of payments that are scheduled to be sent, helping you forecast the amount needed to ensure all payments are successfully processed. ![Image: Outbound Payments -> Account Balance](/images/docs/send-money/payment-account/screenshot_2025-06-24_at_13.19.26.png) The page also offers a few additional features: - Downloading your account statement - Viewing account activity - Viewing pending approvals and scheduled outbound payments not yet reflected in the balance - Withdrawing money from the Payment Account - Configuring funding of the Payment Account - Viewing Payment Account details ## Building your own Payment Account UI We provide API endpoints to support building your own Payment Account UI. Start by retrieving your payment accounts using [List Payment Accounts](/docs/api-reference/payment-account#list-payment-accounts). Once you have payment account IDs, you can use them to pull in related data. To show account activity, use [List Payment Account Transactions](/docs/api-reference/payment-account-transaction#list-payment-account-transactions), which returns all transactions for a given payment account. You can also fetch details of a specific transaction using [Get a single payment account transaction](/docs/api-reference/payment-account-transaction#get-a-single-payment-account-transaction). We generate a new event every time a transaction is recorded on a payment account. Each event triggers a real-time webhook notification, allowing your system to automatically respond to account activity as it happens. For more details, explore the [Events API reference](/docs/api-reference/event) or follow our guide to [set up webhooks](/docs/getting-started/stay-up-to-date-with-webhooks). To display the current balance, fetch it from [Get a single payment account](/docs/api-reference/payment-account#get-a-single-payment-account-details), where the balance is included in the response. To surface information about outbound payments that are scheduled but not yet sent — such as their total amount and count — use [Outbound Payment Statistics](/docs/send-money/tracking-outbound-payments). This endpoint returns aggregated data for outbound payments across different states. ## What's next? #### [API Request Signing](/docs/send-money/api-request-signing) Set up request signing to authenticate your outbound payment API calls. #### [Send an Outbound Payment](/docs/send-money/send-an-outbound-payment) Add a recipient and initiate your first outbound payment. ## Send an Outbound Payment URL: https://docs.gocardless.com/docs/send-money/send-an-outbound-payment > Create, approve, and manage outbound payments from your GoCardless payment account. # Send an Outbound Payment Sending money with GoCardless follows a simple lifecycle: add a recipient, create the payment, approve it after Confirmation of Payee verification, and track it to completion. #### [Add a New Recipient](/docs/send-money/send-an-outbound-payment/add-a-new-recipient) Create and verify a beneficiary account before sending funds. #### [Create an Outbound Payment](/docs/send-money/send-an-outbound-payment/create-an-outbound-payment) Initiate a payment or withdrawal with the required parameters. #### [Approve an Outbound Payment](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment) Review Confirmation of Payee results and approve the payment to send. #### [Cancel an Outbound Payment](/docs/send-money/send-an-outbound-payment/cancel-an-outbound-payment) Cancel a pending payment before it enters the executing state. ## Strong Customer Authentication URL: https://docs.gocardless.com/docs/send-money/strong-customer-authentication > Strong Customer Authentication (SCA) for outbound payments. # Strong Customer Authentication (SCA) **Strong Customer Authentication (SCA)** is a regulatory requirement under the Payment Services Regulations 2017 in the UK and PSD2 in the EEA. It is designed to verify your identity in order to provide protection against fraud. The regulation requires SCA when you make a payment or access your account. You will need to verify your identity using at least two of the following three factors: - _Something you know_ (e.g. a password, PIN, or security question) - _Something you possess_ (e.g. a mobile phone, hardware token, or a smart card) - _Something you are_ (e.g. fingerprint, facial recognition, or other biometric data) ## When you make a payment through our dashboard If you make a payment from the dashboard, you will receive an SMS with an authentication code that is **dynamically linked** to the details of the payment amount and payee, making it difficult for the code to be manipulated or used for another payment. 1. You first log in with your password (_something you know_). ![Image -> Sign In](/images/docs/send-money/strong-customer-authentication/screenshot_2025-10-02_at_15.28.22.png) 2. You will be able to create the payment by inputting the amount and recipient. ![Image: Outbound Payments -> Initiate](/images/docs/send-money/strong-customer-authentication/screenshot_2025-10-07_at_16.27.27.png) 3. After reviewing your payment details, you'll be asked to enter a code sent to your phone (_something you have_). ![Image: Outbound Payments -> SCA dialog](/images/docs/send-money/strong-customer-authentication/screenshot_2025-10-02_at_15.30.18.png) ### Important points to keep in mind 1. **Make sure SMS 2FA is enabled.** You need to have SMS-based 2FA turned on for your account. If it's not, your payment won't go through because we can't send you the code. ![Image: User Settings -> 2-factor authentication](/images/docs/send-money/strong-customer-authentication/screenshot_2025-10-02_at_15.41.57.png) 2. **Approve within 5 minutes.** After you initiate a payment, you have 5 minutes to enter the authentication code. If you do not provide a valid code in time, the payment will be cancelled. You have 5 attempts to authenticate. After 5 failed attempts, your account will be blocked from making outbound payments or withdrawals for 15 minutes. 3. **Resend the authentication code.** You can request to resend the authentication code up to two times. If you still don't approve the payment after the retries, it will be cancelled after 5 minutes. ## Exemptions to SCA The regulations provide a few exemptions from SCA for outbound payments. At GoCardless, we support the **Trusted Beneficiary** exemption. When you make a payment to a recipient and SCA is applied, they are added to a trusted list so that subsequent payments can proceed without requiring authentication. GoCardless automatically maintains a list of trusted beneficiaries — you cannot manage or edit this list. A recipient is automatically marked as trusted after the first successful payment sent to them that includes a completed SCA and passes the Confirmation of Payee check with `full_match` results. > **Info:** > Once trusted, a recipient remains on the list unless no payment is made to them for 13 months. If > the 13-month period lapses, they are removed and SCA will be triggered on the next payment. ## What do you need to do if you don't use the GoCardless Dashboard? If you're building your own API integration, you must include your organisation's authorisation token in every request (_something you know_). You should also sign your API requests with your organisation's certificate (_something you own_) to verify their authenticity. This helps ensure security and compliance with PSD2 regulations. ## What's next? #### [Bank Account Holder Verification](/docs/send-money/bank-account-holder-verification) Understand how Confirmation of Payee checks work and how to interpret the results. #### [API Request Signing](/docs/send-money/api-request-signing) Set up request signing to meet the API authentication requirements. ## Tracking Outbound Payments URL: https://docs.gocardless.com/docs/send-money/tracking-outbound-payments > Track the status of outbound payments. # Get the details of your outbound payments To retrieve the details of a specific outbound payment, use the following API call. ```http GET https://api.gocardless.com/outbound_payments/{outbound_payment_id} HTTP/1.1 HTTP/1.1 200 Content-Type: application/json { "outbound_payments": { "id": "OUT01JR7P5PKW3K7Q34CJAWC03E82", "created_at": "2024-11-28T22:51:46.129Z", "status": "pending", "reference": "GC-w2GJBgZkXU9opeB", "description": "My first payment", "scheme": "faster_payments", "amount": 100, "is_withdrawal": false, "execution_date": "2024-11-28", "metadata": null, "links": { "recipient_bank_account": "BA000123", "creditor": "CR0000123" }, "verifications": { "recipient_bank_account_holder_verification": { "type": "confirmation_of_payee", "result": "full_match", "actual_account_name": null } } } } ``` The next example demonstrates how to fetch a paginated list of outbound payments. Providing a time window (`created_from` – `created_to`) is mandatory and must not exceed one month. ```http GET https://api.gocardless.com/outbound_payments?created_from=2024-11-01&created_to=2024-11-30 HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json { "outbound_payments": [ { "id": "OUT01JR7P5PKW3K7Q34CJAWC03E82", "created_at": "2024-11-28T22:51:46.129Z", "status": "pending", "reference": "GC-w2GJBgZkXU9opeB", "description": "My first payment", "scheme": "faster_payments", "amount": 100, "is_withdrawal": false, "execution_date": "2024-11-28", "metadata": null, "links": { "recipient_bank_account": "BA000123", "creditor": "CR0000123" }, "verifications": { "recipient_bank_account_holder_verification": { "type": "confirmation_of_payee", "result": "full_match", "actual_account_name": null } } } ], "meta": { "cursors": { "before": null, "after": null }, "limit": 50 } } ``` > **Info:** > Both the single-payment and list endpoints operate asynchronously. Newly created outbound payments > may not be immediately visible if you query the API right after creation. Allow a short delay > before retrieving or listing payments to ensure accurate results. ## Outbound payment status To track the processing stage of your outbound payment, refer to its **status**, which indicates the current step in the payment lifecycle. | Status | Description | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `verifying` | Initial state. The payment has been created and verification is in progress. No action is required at this stage. | | `pending_approval` | The payment is awaiting approval and cannot be scheduled without it. | | `scheduled` | Verification and approval are complete, but processing has not yet begun. Future-dated payments remain here until their execution date arrives. | | `executing` | The execution date has arrived and the payment has been queued for processing. Payments in this state can no longer be cancelled. | | `executed` | The payment has been accepted by the scheme and is on its way to the recipient. | | `failed` | The payment failed, usually due to an error while executing. In rare cases, a payment can fail after being executed if rejected by the recipient bank. | | `cancelled` | The payment was cancelled — either via the cancel API, or because the merchant failed to approve or cancel it in time. Cancelled payments can no longer be approved or scheduled. | ## Staying up to date with events We generate events for every status change related to your outbound payments, except for the `verifying` and `scheduled` statuses. Events enable you to track the progress of your payments efficiently. You can learn more about events in the [API Reference](/docs/api-reference/events/payment). Each event also triggers a webhook, allowing you to receive real-time notifications whenever there's an update to your outbound payment. For more information on setting up webhooks, check out [this guide](/docs/getting-started/stay-up-to-date-with-webhooks). > **Info:** > Failed event webhooks include a `cause` field to help identify the reason for failure. Detailed > descriptions are available in the [API Reference](/docs/api-reference/events/outbound-payment). ## What's next? #### [Bank Account Holder Verification](/docs/send-money/bank-account-holder-verification) Understand how Confirmation of Payee checks work and how to interpret verification results. #### [Strong Customer Authentication](/docs/send-money/strong-customer-authentication) Learn how SCA works and which payments qualify for an exemption. ## Approve an Outbound Payment URL: https://docs.gocardless.com/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment > Approve a pending outbound payment. # Approve an outbound payment To enhance security and compliance, we have implemented a mandatory approval process for all outbound payments. Your outbound payment will not be sent until you explicitly confirm that you have reviewed the payment details and agree to proceed, because: - Instant outbound payments cannot be cancelled once initiated, as we immediately start the money transfer process. The approval step allows you time to double-check the payment details before it is too late. - As part of our compliance process, we run verification checks such as **Confirmation of Payee** to help prevent misdirected payments. See [Bank Account Holder Verification](/docs/send-money/bank-account-holder-verification) for more details. ## Approval process An outbound payment can only be approved after all verification checks are completed. This ensures you can review the payment details and verification results before giving the go-ahead. The outbound payment will enter the **`pending_approval`** state, and you will receive the **`set_to_pending_approval`** webhook notification. ### Steps 1. Upon receiving the **`set_to_pending_approval`** webhook, retrieve the payment details and carefully review the response, paying special attention to the verification results. See [Bank Account Holder Verification](/docs/send-money/bank-account-holder-verification) for guidance on interpreting results, and [Tracking Outbound Payments](/docs/send-money/tracking-outbound-payments) for how to retrieve payment details. 2. If you are ready to proceed, use the designated API endpoint to approve the payment: ```http POST https://api.gocardless.com/outbound_payments/{outbound_payment_id}/actions/approve HTTP/1.1 ``` 3. If you notice an error in the details or have concerns about the verification results and do not wish to proceed, you can cancel the payment. See [Cancel an Outbound Payment](/docs/send-money/send-an-outbound-payment/cancel-an-outbound-payment). 4. Upon successful approval, the payment will transition to the next appropriate state. ## What's next? #### [Tracking Outbound Payments](/docs/send-money/tracking-outbound-payments) Monitor payment status changes and lifecycle events after approval. #### [Strong Customer Authentication](/docs/send-money/strong-customer-authentication) Learn how SCA works and which payments qualify for an exemption. ## Cancel an Outbound Payment URL: https://docs.gocardless.com/docs/send-money/send-an-outbound-payment/cancel-an-outbound-payment > Cancel a pending outbound payment. # Cancel an outbound payment ## Eligibility Once an outbound payment moves to the `executing` state or beyond, the payment process has started and cancellation is no longer possible. | Payment type | Cancellable states | | ------------------------------ | -------------------------------------------- | | Instant outbound payments | `verifying`, `pending_approval` | | Future-dated outbound payments | `verifying`, `pending_approval`, `scheduled` | ## Use cases for cancellation 1. The payment is no longer necessary — for example, the recipient no longer requires the funds, or a business decision changes the need for the payment. 2. You have concerns about the verification results and do not wish to proceed. 3. Since outbound payments cannot be directly updated, cancellation is required if any attributes need to be changed. To modify the amount, description, or other parameters, cancel the existing payment and create a new one. ## No recall process > **Warning:** > Once an outbound payment is processed and executed, it cannot be recalled. If funds are sent to > the wrong recipient or with the wrong amount, the funds are transferred to the recipient's bank > account and we no longer have access to them. ## Example ```http POST https://api.gocardless.com/outbound_payments/{outbound_payment_id}/actions/cancel HTTP/1.1 ``` ## What's next? #### [Create an outbound payment](/docs/send-money/send-an-outbound-payment/create-an-outbound-payment) Create a new outbound payment with the corrected details. #### [Tracking Outbound Payments](/docs/send-money/tracking-outbound-payments) Monitor payment status and understand the full lifecycle. ## Create an Outbound Payment URL: https://docs.gocardless.com/docs/send-money/send-an-outbound-payment/create-an-outbound-payment > Create an outbound payment request. # Create an outbound payment There are two types of outbound payments you can create: **regular outbound payments** (sent to the recipient you specify) and **withdrawals** (transferred to your verified business bank account). ## Regular outbound payments Let's create your first outbound payment. At a minimum, you need to specify the following details: - `amount` in minor units (e.g., pence for GBP, cents for EUR) - `scheme` — the payment scheme you want to use - `recipient_bank_account` — your customer bank account ID > **Info:** > The Outbound Payment API enforces idempotent creation to prevent duplicate payments. The > **Idempotency-Key** header is mandatory. For details, refer to the [API > reference](/docs/api-reference/limits#idempotency-keys). Here's an example to guide you: ```http POST https://api.gocardless.com/outbound_payments HTTP/1.1 { "outbound_payments": { "amount": 10000, "scheme": "faster_payments", "description": "Affiliate Program Payout – January", "links": { "recipient_bank_account": "BA0001AA111AAA" } } } ``` ## Withdrawals Withdrawals are essentially regular outbound payments — they follow the same lifecycle, events, creation and cancellation process, and other behaviours. The only difference is that withdrawals are sent to your nominated (and verified) bank account. A separate endpoint is provided for convenience, as you don't need to specify a recipient. Withdrawals are useful when you wish to move funds out of your Payment Account. This is particularly relevant for organisations using the _Funding from Collections_ model, where payouts from Collections accumulate in your Payment Account unless a withdrawal is made. > **Info:** > All unassigned funds are automatically paid out to your nominated business bank account quarterly > — on the first Tuesday of each January, April, July, and October. Here's an example of creating a withdrawal: ```http POST https://api.gocardless.com/outbound_payments/withdrawal HTTP/1.1 { "outbound_payments": { "amount": 10000, "scheme": "faster_payments", "description": "Surplus Payout January" } } ``` ## Scheduling future-dated outbound payments In the standard scenario for instant schemes such as Faster Payments, your outbound payment is sent immediately and typically reaches the recipient's bank account within seconds (in rare cases it may take up to a few hours). To schedule a payment for a specific future date, set the `execution_date` field: ```http POST https://api.gocardless.com/outbound_payments HTTP/1.1 { "outbound_payments": { "amount": 10000, "scheme": "faster_payments", "description": "Affiliate Program Payout – January", "execution_date": "2025-01-01", "links": { "recipient_bank_account": "BA0001AA111AAA" } } } ``` ## What's next? #### [Approve an outbound payment](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment) Review Confirmation of Payee results and approve the payment to send it. #### [Cancel an outbound payment](/docs/send-money/send-an-outbound-payment/cancel-an-outbound-payment) Cancel a pending payment before it enters the executing state. ## Send an Outbound Payment URL: https://docs.gocardless.com/docs/send-money/send-an-outbound-payment/add-a-new-recipient > Create a recipient for outbound payments. # Create a recipient Before sending money, ensure that GoCardless has the recipient's bank details. Recipients can either be: - Existing customers who you already collect payments from - New customers If you've used the GoCardless API before, this process will be straightforward. If you're new to the API, take a moment to explore the API reference and examples via the links below. In summary, you'll need to work with two key endpoints: - [Create a customer](/docs/api-reference/customer#create-a-customer) - [Create a customer bank account](/docs/api-reference/customer-bank-account#create-a-customer-bank-account) Once created, you can use the same recipient to send outbound payments as many times as needed. ## What's next? #### [Initiate an outbound payment](/docs/send-money/send-an-outbound-payment/create-an-outbound-payment) Create a regular outbound payment or withdrawal with the required parameters. #### [Approve an outbound payment](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment) Review verification results and approve the payment to send it. --- # Bank Account Data ## Overview URL: https://docs.gocardless.com/docs/bank-account-data > Overview of GoCardless Bank Account Data. # Overview ## Account Information API Documentation ## Introduction This document explains how to integrate with Bank Account Data API to connect to your users' bank accounts and access account information from bank PSD2 APIs. Bank Account Data API is a set of endpoints that allows you to integrate our Account Information solution with your system. All responses will be shown in JSON format. All endpoints require the Authorization token. Before you start, please make sure you have acquired a user secret from GoCardless's [**Bank Account Data portal**](https://bankaccountdata.gocardless.com/login/) To jump-start your integration, head straight to the [Quickstart Guide](/docs/bank-account-data/quickstart-guide). ## Available data Account Information solution can access up to 24 months of transaction history as well as up to 90 days of continuous access to account information. Our Account Information solution provides access to the following data: - [**Account**](/docs/bank-account-data/output-account-details)**: account holder name, a list of account holder's accounts (account number, IBAN)** - [**Transactions**](/docs/bank-account-data/output-transaction-details)**: date, merchant or counterparty (partner) name, description (info field), amount** - [**Balances**](/docs/bank-account-data/output-balances)**: current and available** ## Coverage Our Account Information solution is available in all European Economic Area countries that are subject to PSD2 regulation. In all these countries GoCardless (GoCardless SAS (in EEA) or GoCardless Ltd. (in the UK)) operates as an authorized AISP. You can find the full list of banks and their details [**here**](https://docs.google.com/spreadsheets/d/1EZ5n7QDGaRIot5M86dwqd5UFSGEDTeTRzEq3D9uEDkM/). ## Authentication To use Account Information API, you are required to have access to GoCardless's [**Bank Account Data portal**](https://bankaccountdata.gocardless.com/user-secrets/) and acquire user secrets. User secrets are used to create access tokens which in turn are used for client authentication and API request authorisation. More information about credential creation and deletion [**_here_**](https://bankaccountdata.zendesk.com/hc/en-gb/articles/11529532364700-Token-handling-via-API). ## Rate Limits Banks may impose rate limits, down to 4 API calls per day for every account. Each endpoint (details, balances, transactions) has it own rate limit. If you exceed the rate limit, you will get an error. #### Rate Limit Headers To improve your API experience, our API provides a set of response headers with your API requests. These headers will give you more insight into your rate limits: **General Rate Limits** (applicable to all API requests): - `HTTP_X_RATELIMIT_LIMIT`: indicates the maximum number of allowed requests within the defined time window. - `HTTP_X_RATELIMIT_REMAINING`: shows the number of remaining requests you can make in the current time window. - `HTTP_X_RATELIMIT_RESET`: provides the time remaining in the current window. **Account Success Request** (additional headers per access scope for account details, transactions, and balances): - `HTTP_X_RATELIMIT_ACCOUNT_SUCCESS_LIMIT`: indicates the maximum number of allowed requests within the defined time window. - `HTTP_X_RATELIMIT_ACCOUNT_SUCCESS_REMAINING`: shows the number of remaining requests you can make in the current time window. - `HTTP_X_RATELIMIT_ACCOUNT_SUCCESS_RESET`: provides the time remaining in the current window, in seconds. These account success request headers will only be present for successful account resource requests. It's important to note that failed requests against details, balances and transactions endpoints, regardless of the error type, will not count against the account success request rate limits, but they will count towards the [general rate limits](https://bankaccountdata.zendesk.com/hc/en-gb/articles/11529637772188-Bank-Account-Data-API-Rate-Limits). #### Handling Rate Limit Errors If the limit is reached, a `RateLimitError` will be returned whenever you attempt to make an API call: ```json { "summary": "Rate limit exceeded", "detail": "The rate limit for this resource is \/\. Please try again in \ seconds", "status_code": 429 } ``` When you receive a `RateLimitError`, the only option is to wait until the time returned in the `HTTP_X_RATELIMIT_ACCOUNT_SUCCESS_RESET` header has passed to execute your request. There is no need to reconnect the account before trying again. ## Customer Journey The diagram below depicts an example of the customer journey for our clients' end users. ![Customer Journey - Bank Account Data](/images/docs/bank-account-data/customer_journey.png) ### Process Description 1. You assign a unique reference number to each of your end users, which is later used to identify the respective end user. With the unique identifier assigned, the end user then sees the first view, which is developed and hosted by you. 2. The end user is shown which financial institution they can link with the service. The list of available financial institutions is retrieved from the Bank Account Data API and depends on financial institutions GoCardless supports within any given country. 3. After the end user selects a financial institution, they are taken to the second view, which contains a consent text. This view is hosted by GoCardless. When the end user has accepted consent, they are directed to the next view. 4. The financial institution provides an interface for the end user to link their account data. This view is developed and hosted by the financial institution, therefore, neither you nor GoCardless can influence the look and feel of this view\*. The financial institution view depends on each financial institution. 5. After successful authentication, their access token is securely stored on the GoCardless side. The access token enables GoCardless to fetch bank account data from the respective financial institution. 6. As the final step, the end user is redirected to URL specified by you. If necessary, you can ask the end user to link another financial institution or conclude the process. If the authentication wasn't successful where either the end user decided not to proceed, or the user did provide a wrong user name and/or password, the end user is redirected back to the initial application view, developed and hosted by you. The error message is attached as a query parameter in this case. Once the end user has successfully concluded the process, you can access the raw data via the Bank Account Data API. - Certain financial institutions do not provide their views for user authentication; they rely on GoCardless to provide means of collecting the end-user credentials. **GoCardless does not store nor process the end-user credentials!** ## Verification New accounts have "non-verified" status, and your end-users will see an informative message (see image below). This doesn't impact any other features you are able to access on the API. Account verification is only offered to paying customers - if you'd like to discuss your options, please [contact our team](https://bankaccountdata.zendesk.com/hc/en-gb/requests/new). ![Overview - Bank Account Data](/images/docs/bank-account-data/screenshot_2023-10-30_at_17.31.10.png) ## What's next? #### [Quickstart Guide](/docs/bank-account-data/quickstart-guide) Follow a step-by-step guide to connect your first bank account and retrieve transaction data. #### [Account Details](/docs/bank-account-data/output-account-details) Understand the account holder name and account number fields returned by the API. #### [Transactions](/docs/bank-account-data/output-transaction-details) Retrieve and interpret transaction history including merchant name, amount, and description. #### [Statuses and Error Codes](/docs/bank-account-data/statuses-and-error-code) Handle errors and understand the full set of status codes returned by the API. ## Bank Selection UI URL: https://docs.gocardless.com/docs/bank-account-data/bank-selection-ui > Bank selection UI for Bank Account Data. # Bank Selection UI This guide explains how to create end-user-facing UI to select the end-users bank. ## Step 1: Find Banks First, query `institutions` endpoint to get a list of all available financial institutions in a given country. ```bash curl -X GET "https://bankaccountdata.gocardless.com/api/v2/institutions/?country=gb" -H "accept: application/json" -H "Authorization: Bearer ACCESS_TOKEN" ``` Response: ```json [ { "id": "ABNAMRO_ABNAGB2LXXX", "name": "ABN AMRO Bank Commercial", "bic": "ABNAGB2LXXX", "transaction_total_days": "540", "countries": [ "GB" ], "logo": "https://cdn-logos.gocardless.com/ais/ABNAMRO_FTSBDEFAXXX.png" }, [...] { "id": "REVOLUT_REVOGB21", "name": "Revolut", "bic": "REVOGB21", "transaction_total_days": "730", "countries": [ "GB" ], "logo": "https://cdn-logos.gocardless.com/ais/REVOLUT_REVOGB21.png" }, ] ``` ## Step 2: Create a UI element You will need to create a UI or any other mechanism for selecting the end user's bank. To build the UI element you can either: - use [open source JavaScript library](https://github.com/nordigen/nordigen-bank-ui) built by GoCardless that already incorporates best practices or, - build the UI from scratch Here are some considerations if UI is built from scratch: 1. Have a clear call to action e.g. "Select your bank". 2. Include additional support text if necessary. It's twice more likely that the end user goes trough Open Banking journey if the value proposition is stated clearly. 3. Show available banks. Considerations: - Show both logo and a name of a bank; - Sort banks in alphabetical order or by popularity; - You can list all available banks in a given country or select only those ones that are used by your customer base; - Instead of listing the banks, show banks in a grid form if the bank list is not extensive. 4. Add a bank search bar for better UX. 5. Use styles that fit with the rest of your application. ## Step 3: Add Institution ID association Once the end user selects their bank, make sure to pass the correct Institution ID when building the requisition and the link to start the end-user authentication process with the selected financial institution (see step 4 in the [Quickstart Guide](/docs/bank-account-data/quickstart-guide)). ## What's next? #### [Quickstart Guide](/docs/bank-account-data/quickstart-guide) Complete the integration by building the requisition and authentication link. #### [Sandbox](/docs/bank-account-data/sandbox) Test your bank selection UI against the Sandbox Finance mock bank. ## Output: Account Details URL: https://docs.gocardless.com/docs/bank-account-data/output-account-details > Account details output from Bank Account Data. # Account Details ## Account Details This section contains key descriptions for accounts. | KEY | TYPE | OPTIONAL | DESCRIPTION | | ---------------------------- | ----------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **bban** | Max128Text | Optional | This data element is used for payment accounts which have no IBAN | | **bic** | Max128Text | Optional | The BIC associated to the account. | | **cashAccountType** | Cash Account Type | Optional | ExternalCashAccountType1Code from ISO 20022 | | **currency** | Max3Text | Mandatory | Account currency | | **details** | Max512Text | Optional | Specifications that might be provided by the financial institution - characteristics of the account - characteristics of the relevant card | | **displayName** | Max128Text | Optional | Name of the account as defined by the end user within online channels | | **iban** | Max34Text | Optional | | | **linkedAccounts** | Max128Text | Optional | This data attribute is a field, where an financial institution can name a cash account associated to pending card transactions. | | **msisdn** | Max64Text | Optional | An alias to a payment account via a registered mobile phone number | | **name** | Max128Text | Optional | Name of the account, as assigned by the financial institution | | **ownerAddressUnstructured** | Max256Text | Optional | Address of the legal account owner | | **ownerName** | Max256Text | Optional | Name of the legal account owner. If there is more than one owner, then e.g. two names might be noted here. For a corporate account, the corporate name is used for this attribute. | | **product** | Max64Text | Optional | Product Name of the Bank for this account, proprietary definition | | **resourceId** | Max128Text | Conditional | The account id of the given account in the financial institution | | **status** | Max7Text | Optional | Account status. The value is one of the following: "enabled": account is available "deleted": account is terminated "blocked": account is blocked e.g. for legal reasons If this field is not used, then the account is available in the sense of this specification. | | **scan** | Max14Text | Optional | SortCodeAccountNumber returned by some UK banks (6 digit Sort Code and 8 digit Account Number) | | **usage** | Max4Text | Optional | Specifies the usage of the account PRIV: private personal account ORGA: professional account | ## What's next? #### [Output: Balances](/docs/bank-account-data/output-balances) See all balance types returned and what each one represents. #### [Output: Transaction Details](/docs/bank-account-data/output-transaction-details) Explore the transaction data fields including amounts, dates, and remittance information. ## Output: Balances URL: https://docs.gocardless.com/docs/bank-account-data/output-balances > Balance output from Bank Account Data. # Account Balance Output ## Account Balance Output This section contains key descriptions for balances. ### Balance | KEY | TYPE | OPTIONAL | DESCRIPTION | | ----------------------------- | ------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | **balanceAmount** | Amount | Mandatory | an object containing: **amount** Float **currency** Max3Text | | **balanceType** | Balance Type | Mandatory | | | **creditLimitIncluded** | Boolean | Optional | A flag indicating if the credit limit of the corresponding account is included in the calculation of the balance, where applicable. | | **lastChangeDateTime** | ISODateTime | Optional | This data element might be used to indicate e.g. with the expected or booked balance that no action is known on the account, which is not yet booked. | | **lastCommitted Transaction** | Max35Text | Optional | entryReference of the last commited transaction to support the TPP in identifying whether all end users transactions are already known. | | **referenceDate** | ISODate | Optional | indicates the date of the balance | ### Balance Type | TYPE | DESCRIPTION | | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **closingAvailable** | Closing balance of amount of money that is at the disposal of the account owner on the date specified. | | **closingBooked** | Balance of the account at the end of the pre-agreed account reporting period. It is the sum of the opening booked balance at the beginning of the period and all entries booked to the account during the pre-agreed account reporting period. For card-accounts, this is composed of - invoiced, but not yet paid entries | | **closingCleared** | Closing balance of amount of money that is cleared on the date specified. | | **expected** | Balance composed of booked entries and pending items known at the time of calculation, which projects the end of day balance if everything is booked on the account and no other entry is posted. For card accounts, this is composed of - invoiced, but not yet paid entries, - not yet invoiced but already booked entries and - pending items (not yet booked) | | **forwardAvailable** | Forward available balance of money that is at the disposal of the account owner on the date specified. | | **interimAvailable** | Available balance calculated in the course of the account 'servicer's business day, at the time specified, and subject to further changes during the business day. The interim balance is calculated on the basis of booked credit and debit items during the calculation time/period specified. For card-accounts, this is composed of - invoiced, but not yet paid entries, - not yet invoiced but already booked entries | | i**nterimCleared** | Cleared balance calculated in the course of the account servicer's business day, at the time specified, and subject to further changes during the business day. | | **information** | Balance for informational purposes. | | **interimBooked** | Balance calculated in the course of the account servicer's business day, at the time specified, and subject to further changes during the business day. The interim balance is calculated on the basis of booked credit and debit items during the calculation time/period specified. | | **nonInvoiced** | Only for card accounts, to be defined yet. | | **openingBooked** | Book balance of the account at the beginning of the account reporting period. It always equals the closing book balance from the previous report. | | **openingAvailable** | Opening balance of amount of money that is at the disposal of the account owner on the date specified. | | **openingCleared** | Opening balance of amount of money that is cleared on the date specified. | | **previouslyClosedBooked** | Balance of the account at the previously closed account reporting period. The opening booked balance for the new period has to be equal to this balance. Usage: the previously booked closing balance should equal (inclusive date) the booked closing balance of the date it references and equal the actual booked opening balance of the current date. | ## What's next? #### [Output: Transaction Details](/docs/bank-account-data/output-transaction-details) Explore the transaction data fields including amounts, dates, and remittance information. #### [Endpoints](/docs/bank-account-data/endpoints) Full API reference for all Bank Account Data endpoints. ## Output: Transaction Details URL: https://docs.gocardless.com/docs/bank-account-data/output-transaction-details > Transaction details output from Bank Account Data. # Account Transactions Output ## Account Transactions Output This section contains key descriptions for transactions. | KEY | TYPE | OPTIONAL | DESCRIPTION | | -------------------------------------------- | ----------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **additionalDataStructured** | Object | Optional | An umbrella datapoint used for information that is outside of Berlin Group specification, such as bank- or country-specific fields | | **additionalInformation** | Max512Text | Optional | Might be used by the financial institution to transport additional transaction related information | | **additionalInformation Structured** | Max280Text | Conditional | Is used if and only if the bookingStatus entry equals "information" | | **balanceAfterTransaction** | Balance | Optional | This is the balance after this transaction. Recommended balance type is interimBooked. | | **bankTransactionCode** | Max32Text | Optional | Bank transaction code as used by the financial institution and using the sub elements of this structured code defined by ISO20022. For standing order reports the following codes are applicable: "PMNT-ICDT-STDO" for credit transfers, "PMNT-IRCT-STDO" for instant credit transfers, "PMNT-ICDT-XBST" for cross-border credit transfers, "PMNT-IRCT-XBST" for cross-border real time credit transfers, "PMNT-MCOP-OTHR" for specific standing orders which have a dynamical amount to move left funds e.g. on month end to a saving account | | **bookingDate** | ISODate | Optional | The date when an entry is posted to an account on the financial institutions books. | | **bookingDateTime** | ISODate | Optional | The date and time when an entry is posted to an account on the financial institutions books. | | **checkId** | Max48Text | Optional | Identification of a Cheque | | **creditorAccount** | Account Reference | Conditional | | | **creditorAgent** | BICFI | Optional | | | **creditorId** | Max35Text | Optional | Identification of Creditors, e.g. a SEPA Creditor ID | | **creditorName** | Max176Text | Optional | Name of the creditor if a "Debited" transaction | | **currencyExchange** | CurrencyExchange can be either a list or a dict | Optional | | | **debtorAccount** | Account Reference | Conditional | | | **debtorAgent** | BICFI | Optional | | | **debtorName** | Max176Text | Optional | Name of the debtor if a "Credited" transaction | | **endToEndId** | Max35Text | Optional | Unique end to end ID | | **entryReference** | Max128Text | Optional | Is the identification of the transaction as used for reference given by financial institution. | | **internalTransactionId** | Max32Text | Optional | Transaction identifier given by Gocardless | | **mandateId** | Max48Text | Optional | Identification of Mandates, e.g. a SEPA Mandate ID | | **merchantCategoryCode** | Max4Text | Optional | Merchant category code as defined by card issuer | | **proprietaryBank** **TransactionCode** | Max64Text | Optional | Proprietary bank transaction code as used within a community or within an financial institution | | **purposeCode** | Purpose Code | Conditional | | | **remittanceInformation Structured** | Max560Text | Optional | Reference as contained in the structured remittance reference structure | | **remittanceInformation StructuredArray** | Array of Remittance | Optional | Reference as contained in the structured remittance reference structure | | **remittanceInformation Unstructured ** | Max560Text | Optional | | | **remittanceInformation UnstructuredArray ** | Array of Max560Text | Optional | | | **transactionAmount** | Amount | Mandatory | The amount of the transaction as billed to the account, an object containing: **amount** Float **currency** Max3Text | | **transactionId** | Max256Text | Optional | Transaction identifier provided by the financial institution | | **ultimateCreditor** | Max128Text | Optional | | | **ultimateDebtor** | Max96Text | Optional | | | **valueDate** | ISODate | Optional | The Date at which assets become available to the account owner in case of a credit | | **valueDateTime** | ISODate | Optional | The date and time at which assets become available to the account owner in case of a credit | ## What's next? #### [Endpoints](/docs/bank-account-data/endpoints) Full API reference for all Bank Account Data endpoints. #### [Statuses and Error Code](/docs/bank-account-data/statuses-and-error-code) Understand account statuses and the error codes returned by the API. ## Postman Collection URL: https://docs.gocardless.com/docs/bank-account-data/postman-collection > Postman collection for Bank Account Data API. # Instructions for Postman ## Instructions for Postman This is a short guide on how to set up Postman. To import a collection, select Collections > Import > Link and enter the following link [https://bankaccountdata.gocardless.com/api/swagger.json](https://bankaccountdata.gocardless.com/api/swagger.json) When importing, set Schema for both Request parameter generation and Response parameter generation under Advanced Options. After importing, you should have a new collection named "Bank Account Data API" and a new API defined. Head to Collections, click "Bank Account Data API", and do the following: - Under Authorization, change the authorization value from `true `to `Bearer YOUR_TOKEN`. Since all requests inherit the security settings from the parent, they will use the token that you've configured here. Save the settings. An example value: `Bearer 848774FFDEDFAKETOKEN88483AC12` Now your Postman is set up and you can continue instructions from [Quickstart Guide](/docs/bank-account-data/quickstart-guide). ## What's next? #### [Quickstart Guide](/docs/bank-account-data/quickstart-guide) Follow the step-by-step guide to connect your first bank account. #### [Sandbox](/docs/bank-account-data/sandbox) Test your integration using the Sandbox Finance mock bank. ## Quickstart Guide URL: https://docs.gocardless.com/docs/bank-account-data/quickstart-guide > Get started quickly with GoCardless Bank Account Data. # Quickstart Guide This document explains how to jump-start your integration with the Bank Account Data API. For more detailed information on endpoint input parameters and response details, refer to section [Endpoints](/docs/bank-account-data/endpoints). If you are using Postman, you can follow these [instructions](/docs/bank-account-data/postman-collection) on how to import Bank Account Data API schema. ## Step 1: Get User Secrets First, you'll need to get your user secret from [GoCardless's Bank Account Data portal](https://bankaccountdata.gocardless.com/user-secrets/) in section User Secrets. Use these secrets to create a refresh token. ## Step 2: Get Refresh Token The POST /api/v2/token/new/ endpoint takes the secret_id and secret_key and returns a long-lived refresh token. ```bash curl -X POST "https://bankaccountdata.gocardless.com/api/v2/token/new/" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ -d "{\"secret_id\":\"string\", \"secret_key\":\"string\"}" ``` Response: ```json { "refresh": "string", "refresh_expires": 2592000 } ``` ## Step 3: Refresh Your Access Token The POST /api/v2/token/refresh/ endpoint is used subsequently to exchange the refresh token for a new access token. When the access token is nearing expiry, use your stored refresh token to get a new, valid access token for continued API access. This avoids the need to go back to the user secrets. ```bash curl -x POST 'https://bankaccountdata.gocardless.com/v2/token/refresh/' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "refresh": "REFRESH token from /api/v2/token/new/ " } ``` Response: ```json { "access": "string", "access_expires": 86400 } ``` ## Step 4: Choose a Bank Use institutions endpoint to get a list of all available financial institutions in a given country. You will need to provide a two-letter country code ([ISO 3166](https://en.wikipedia.org/wiki/ISO_3166-1)). ID for the chosen bank will be used in the following steps (referenced as institution_id). Use SANDBOXFINANCE_SFIN0000 as institution_id if you wish to try out the Quickstart with the mock-up institution (see [Sandbox](/docs/bank-account-data/sandbox)). See also the [guide](/docs/bank-account-data/bank-selection-ui) on how to build an end user interface for selecting a bank. ```bash curl -X GET "https://bankaccountdata.gocardless.com/api/v2/institutions/?country=gb" \ -H "accept: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" ``` Response: ```json [ { "id": "ABNAMRO_ABNAGB2LXXX", "name": "ABN AMRO Bank Commercial", "bic": "ABNAGB2LXXX", "transaction_total_days": "540", "countries": [ "GB" ], "logo": "https://storage.googleapis.com/gc-prd-institution_icons-production/UK/PNG/abnamrobank.png", "max_access_valid_for_days": "90", "max_access_valid_for_days_reconfirmation": "730" }, { "..." }, { "id": "REVOLUT_REVOGB21", "name": "Revolut", "bic": "REVOGB21", "transaction_total_days": "730", "countries": [ "GB" ], "logo": "https://storage.googleapis.com/gc-prd-institution_icons-production/UK/PNG/revolut.png", "max_access_valid_for_days": "90", "max_access_valid_for_days_reconfirmation": "730" } ] ``` ## Step 5: Create an end user agreement **NB!** Use this step only if you want to specify other than default end user agreement terms: 90 days of transaction history, 90 days of account access period and full scope of information (details, balances, transactions). If no custom end user agreement is created, default terms will be applied. You need to create an agreement and pass: - institution_id from Step 2. And optionally: - max_historical_days as the length of the transaction history to be retrieved; - access_valid_for_days as the length of days while the access to account is valid; - access_scope for the scope of information. ```bash curl -X POST "https://bankaccountdata.gocardless.com/api/v2/agreements/enduser/" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" \ -d "{\"institution_id\": \"REVOLUT_REVOGB21\", \"max_historical_days\": \"180\", \"access_valid_for_days\": \"30\", \"access_scope\": [\"balances\", \"details\", \"transactions\"] }" ``` Response: ```json { "id": "2dea1b84-97b0-4cb4-8805-302c227587c8", "created": "2021-10-25T16:41:09.753Z", "max_historical_days": 180, "access_valid_for_days": 30, "access_scope": ["balances", "details", "transactions"], "accepted": "", "institution_id": "REVOLUT_REVOGB21" } ``` ## Step 6: Build a Link You need to create a requisition, which is a collection of inputs for creating links and retrieving accounts. For requisition API requests you will need to provide: - institution_id from Step 2; - redirect URL where the end user will be redirected after finishing authentication in financial institution; And optionally: - reference as a unique ID defined by you for internal referencing; - agreement as end user agreement ID from Step 3; - user_language to enforce a language for all end user steps hosted by GoCardless passed as a two-letter country code ([ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). If user_language is not defined a language set in browser will be used to determine language. ```bash curl -X POST "https://bankaccountdata.gocardless.com/api/v2/requisitions/" \ -H "accept: application/json" -H "Content-Type: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" \ -d "{\"redirect\": \"http://www.yourwebpage.com\", \"institution_id\": \"REVOLUT_REVOGB21\", \"reference\": \"124151\", \"agreement\": \"2dea1b84-97b0-4cb4-8805-302c227587c8\", \"user_language\":\"EN\" }" ``` Response: ```json { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created": "2025-05-14T11:05:56.276Z", "redirect": "http://www.yourwebpage.com", "status": "CR", "institution_id": "string", "agreement": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "reference": "string", "accounts": [], "user_language": "EN", "link": "https://ob.gocardless.com/psd2/start/3fa85f64-5717-4562-b3fc-2c963f66afa6/{$INSTITUTION_ID}", "ssn": "string", "account_selection": false, "redirect_immediate": false } ``` Follow the link to start the end-user authentication process with the financial institution. Save the requisition ID (id in the response). You will later need it to retrieve the list of end-user accounts. ## Step 7: List accounts Once the user is redirected back to the link provided in Step 4, the user's bank accounts can be listed. Pass the requisition ID to view the accounts. ```bash curl -X GET "https://bankaccountdata.gocardless.com/api/v2/requisitions/8126e9fb-93c9-4228-937c-68f0383c2df7/" \ -H "accept: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" ``` Response: ```json { "id": "8126e9fb-93c9-4228-937c-68f0383c2df7", "status": "LN", "agreements": "2dea1b84-97b0-4cb4-8805-302c227587c8", "accounts": ["065da497-e6af-4950-88ed-2edbc0577d20", "bc6d7bbb-a7d8-487e-876e-a887dcfeea3d"], "reference": "124151" } ``` ## Step 8: Access account details, balances and transactions There are three separate endpoints for accessing account details, balances, and transactions. See account [endpoints](/docs/bank-account-data/endpoints) to view respective endpoints. In this quickstart, we will showcase the transactions' endpoint, where you need to pass the account ID (see "accounts" from the output of Step 5) to access transaction information. You will need to query each account separately. ```bash curl -X GET "https://bankaccountdata.gocardless.com/api/v2/accounts/065da497-e6af-4950-88ed-2edbc0577d20/transactions/" \ -H "accept: application/json" \ -H "Authorization: Bearer ACCESS_TOKEN" ``` Response: ```json { "transactions": { "booked": [ { "transactionId": "2020103000624289-1", "debtorName": "MON MOTHMA", "debtorAccount": { "iban": "GL53SAFI055151515" }, "transactionAmount": { "currency": "EUR", "amount": "45.00" }, "bookingDate": "2020-10-30", "valueDate": "2020-10-30", "remittanceInformationUnstructured": "For the support of Restoration of the Republic foundation" }, { "transactionId": "2020111101899195-1", "transactionAmount": { "currency": "EUR", "amount": "-15.00" }, "bankTransactionCode": "PMNT", "bookingDate": "2020-11-11", "valueDate": "2020-11-11", "remittanceInformationUnstructured": "PAYMENT Alderaan Coffe" } ], "pending": [ { "transactionAmount": { "currency": "EUR", "amount": "-10.00" }, "valueDate": "2020-11-03", "remittanceInformationUnstructured": "Reserved PAYMENT Emperor's Burgers" } ] } } ``` ## What's next? You can now connect to end-user bank accounts and retrieve raw account and transaction data. Data structures vary between banks — some may include fields like `ownerName` while others may not. If you spot any specific issues, [contact us](https://bankaccountdata.zendesk.com/hc/en-gb/requests/new). #### [Output: Account Details](/docs/bank-account-data/output-account-details) Understand the account details fields returned by the API and how to interpret them. #### [Output: Balances](/docs/bank-account-data/output-balances) See all balance types returned and what each one represents. #### [Output: Transaction Details](/docs/bank-account-data/output-transaction-details) Explore the transaction data fields including amounts, dates, and remittance information. #### [Endpoints](/docs/bank-account-data/endpoints) Full API reference for all Bank Account Data endpoints. ## Sandbox URL: https://docs.gocardless.com/docs/bank-account-data/sandbox > Test Bank Account Data in the sandbox. # Sandbox ## Account Information Sandbox We have created Sandbox Finance which is a mock-up bank you can use to test Account Information product. We suggest you follow the [Quickstart Guide](/docs/bank-account-data/quickstart-guide) for integration. Below are the guidelines on how to use Sandbox Finance in that process. ### Applying in Integration There are two steps when one has to provide a unique identifier for an financial institution: creating an end user agreement and building a Link. In those two steps, whenever you need to provide an institution_id, provide SANDBOXFINANCE_SFIN0000 as a value. When the end user accesses the link, it will start a connection with Sandbox Finance. ### Using in End User Flow The end users can provide any input value for user id and code generator fields in the Sandbox Finance authentication page to continue the journey. When the end user authenticates with Sandbox Finance, you can query results similar to any real connection. ![Bank Account Data Sandbox](/images/docs/bank-account-data/sandbox/sandbox_gocardless.png) ## What's next? #### [Quickstart Guide](/docs/bank-account-data/quickstart-guide) Follow the step-by-step guide to build your first integration. #### [Statuses and Error Codes](/docs/bank-account-data/statuses-and-error-code) Understand the statuses returned during sandbox and live testing. ## Statuses and Error Code URL: https://docs.gocardless.com/docs/bank-account-data/statuses-and-error-code > Status codes and error handling for Bank Account Data. # Statuses and Error Messages Learn about statuses and error messages for different Bank Account Data endpoints. ## Statuses ### Requisitions | Short | Long | Description | Stage | | ----- | ------------------------- | -------------------------------------------------------------------------------- | ----- | | `CR` | CREATED | Requisition has been successfully created | 1 | | `GC` | GIVING_CONSENT | End-user is giving consent at GoCardless's consent screen | 2 | | `UA` | UNDERGOING_AUTHENTICATION | End-user is redirected to the financial institution for authentication | 3 | | `RJ` | REJECTED | Either SSN verification has failed or end-user has entered incorrect credentials | 4 | | `SA` | SELECTING_ACCOUNTS | End-user is selecting accounts | 5 | | `GA` | GRANTING_ACCESS | End-user is granting access to their account information | 6 | | `LN` | LINKED | Account has been successfully linked to requisition | 7 | | `EX` | EXPIRED | Access to accounts has expired as set in End User Agreement | 8 | Stage describes the sequence of each possible status, where `1` is the starting status. ### Accounts | Status | Description | | ------------ | ------------------------------------------------------------------------------------------- | | `DISCOVERED` | User has successfully authenticated, and account has been discovered | | `ERROR` | An error was encountered when processing account | | `EXPIRED` | Access to account has expired as set in End User Agreement | | `PROCESSING` | Account is being processed by the institution | | `READY` | Account has been successfully processed | | `SUSPENDED` | Account has been suspended (more than 10 consecutive failed attempts to access the account) | ## End user authentication messages | Status | Description | HTTP status | | -------------------------------- | ------------------------------------------------------------------------------------------------------ | ----------- | | `InstitutionTechnicalError` | A technical error occurred while trying to connect to the institution, please try again. | 500 | | `GoCardlessTechnicalError` | An unexpected error occurred in the GoCardless system. If this error persists, please contact support. | 500 | | `RequisitionLinkReused` | This link has already been used for authorization and is no longer valid. | 400 | | `UserCancelledSession` | User cancelled the session. | 401 | | `UserSessionRejected` | User session rejected due to incorrect credentials or a business exception. | 401 | | `CompanyRequisitionLimitReached` | Free usage limit exceeded. | 402 | | `UnknownError` | An unknown error occurred. | — | ## API error messages All error HTTP codes are `4xx` or `5xx`. Use HTTP status codes for control flow and the error body for informative purposes. Errors are returned in this shape: ```json { "summary": "Unknown institution ID", "detail": "Get institution ID from /institutions/?country={country_code}", "status_code": 400 } ``` ### Institutions | Summary | Detail | HTTP status | | ---------------------------------------- | ------------- | ----------- | | `Unknown fields in the payload` | | 400 | | | Invalid token | 401 | ### Agreements | Summary | Detail | HTTP status | | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------- | | `Incorrect max_historical_days` | `max_historical_days` must be > 0 and \<= \ `transaction_total_days` (int) | 400 | | `End User Agreements cannot be accepted more than once` | | 400 | | `Institution is not operational` | Institution \ is down or under maintenance. Try again later or contact support for more information. | 503 | | `Cannot delete End User Agreement` | Cannot delete accepted End User Agreement: \. Only non-accepted agreements can be deleted. | 400 | | | Invalid token | 401 | ### Requisitions | Summary | Detail | HTTP status | | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | `Invalid redirect URI` | Redirect URI must have a valid URI structure | 400 | | `Invalid EUA` | \ is not a valid UUID. Please specify a valid agreement from `/api/agreements/enduser/` or create a new one. | 400 | | `Incorrect enduser_id` | `enduser_id` in requisition must match the EUA \. Requisition `enduser_id`: \, EUA `enduser_id`: \ | 400 | | `Provided user_language is invalid or not supported` | \ is invalid or not supported | 400 | | `Institution is not operational` | Institution \ is down or under maintenance. Try again later or contact support for more information. | 503 | | | Invalid token | 401 | ### Accounts | Summary | Detail | HTTP status | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | | `Invalid Account ID` | \ is not a valid UUID | 400 | | `End User Agreement (EUA) has expired` | EUA was valid for \ days and expired at \. The end user must reconnect their account with a new EUA and Requisition. | 401 | | `AccessExpiredError` | Access has expired or been revoked. To restore access, reconnect the account. | 401 | | `AccountInactiveError` | Account has been deactivated or no longer exists. | 401 | | `Invalid token` | | 401 | | `AccountAccessForbidden` | Access to the account is forbidden. The user might not have the necessary permissions. | 403 | | `Account Suspended` | This account or its Requisition was suspended due to numerous errors while accessing it. | 409 | | `AccountProcessing` | Account data is currently being processed. Poll `/accounts/\/` and retry when status is `READY`. | 409 | | `RateLimitError` | The daily request limit set by the institution has been exceeded. | 429 | | `UnknownRequestError` | Request to institution returned an unknown error. | 500 | | `ServiceError` | Institution service unavailable. | 503 | | `ConnectionError` | Couldn't connect to institution. | 503 | ## What's next? #### [Endpoints](/docs/bank-account-data/endpoints) Full API reference for all Bank Account Data endpoints. #### [Sandbox](/docs/bank-account-data/sandbox) Test your integration against the Bank Account Data sandbox environment. --- # Optimise ## Blocking Mandates URL: https://docs.gocardless.com/docs/optimise/blocking-mandates > Block suspicious Direct Debit mandates. # Fraud Prevention: Blocking Mandates This guide shows how to block a Direct Debit mandate. > **Info:** > To use this feature, your organisation must have the Protect+ upgrade enabled - please [get in > touch](mailto:help@gocardless.com) if you would like to use the Block API. ## Overview Merchants experience fraud through a number of different channels. Oftentimes, particularly for chargebacks, they notice similar payers signing up, again and again, to try and defraud them. Until now merchants did not have a way for blocking these fraudulent payers. This feature provides the capability for merchants to create a blocklist for fraudulent payers based on `email_id`, `email_domain`, and `bank_account`. We match against this blocklist when the payer is setting up the mandate and block the mandate if there is a match. ## What can be blocked? The blocking feature is applicable only for Direct Debit mandates and can be used across all schemes except for the `faster_payments`. Pay By Banks will not be blocked. For Instant First Payment where the DD mandate is set up along with the Pay By Bank, only the DD mandate will be blocked, the Pay By Bank will be allowed to go through successfully. ## Effect on API Integration There are no breaking changes for any of the API integrations and merchants need not do anything from their side. The customer would see the success screen when going through the billing request flow or any Payment Pages which means that they have completed the flow but the mandate would fail later on. This would be similar to failed and cancelled mandate. ## Effect of blocking on payments, subscriptions, and instalment_schedules Once a mandate is transitioned to a blocked state it becomes inactive and behaves similar to cancelled and failed mandates. We will not be able to create any payments or subscriptions. Blocking has no impact on existing mandates and payments. Only new mandates set up after the block is in place will be impacted. ## Adding details to blocklists This can be done by following the instructions for the Block API [here](/docs/api-reference/block#create-a-block) There is also a support interface, details about this can be found [here](https://support.gocardless.com/hc/en-gb/articles/17143482877084-Blocklists-FAQ#Can-I-only-use-Blocklists-via-the-GoCardless-API) ## Notifications ### Payer notification An email notification is sent to the customer when the mandate is blocked. There won't be any changes to any of the payment pages and the payer will see the success screen. However, we do not tell the customer explicitly that they have been blocked by the organisation in order to avoid them trying different email addresses or bank accounts. We provide the mandate_id as a reference code to the payer in the email which they can use to contact the merchant. ### Merchant notification `mandate_blocked` webhook notification is sent to the merchant when the mandate is blocked. ```json { "events": [ { "id": "EV123", "created_at": "2014-08-03T12:00:00.000Z", "action": "mandate_blocked", "resource_type": "mandates", "links": { "payment": "MD123" }, "details": { "origin": "gocardless", "cause": "mandate_blocked", "description": "The mandate has been blocked because the customer's details matched against an entry in the blocklist populated by you." } } ] } ``` ## Retrieving blocked mandates ### Dashboard Merchant can filter for mandate blocked events in the events tab of the enterprise dashboard. This will list all the mandates blocked. ![Retrieving blocked mandates](/images/docs/optimise/blocking-mandates/retrieving_blocked_mandates.png) ### API Send `GET` API request to mandate endpoint with below filter `GET https://api.gocardless.com/mandates?status=blocked` OR send API request to the events endpoint with the below query parameters `GET https://api.gocardless.com/events?resource_type=mandates&action=blocked` ## Retrieve the block state of a given mandate_id ### Dashboard ![Retrieve the block state of a give mandate id](/images/docs/optimise/blocking-mandates/retrieve_the_block_state_of_a_give_mandate_id.png) ### API Send `GET` API request to mandate endpoint. The status of the mandate will be blocked ```http GET https://api.gocardless.com/mandates/MD0000S2KNTB2V { "mandates": { "id": "MD0000S2KNTB2V", "created_at": "2021-09-01T15:36:09.104Z", "reference": "ANKITHATEST-3YD936", "status": "blocked", "scheme": "bacs", "next_possible_charge_date": null, "payments_require_approval": false, "metadata": {}, "links": { "customer_bank_account": "BA0000S4DSSHQK", "creditor": "CR00008AWM8AC8", "customer": "CU00018NMYB3H1" } } } ``` ## Unblocking payers ### What to do if there is a false positive Since a mandate can not be unblocked, the merchant has to disable the block for this payer and ask the payer to set up the mandate again. Alternatively, merchants using the **Billing Request Flow** or **who have done the Custom Payment Pages** integration using Billing Request can follow the below steps to set up the mandate again and to reduce the number of steps the payer has to go through. #### Using the Billing Request Flow ##### Step 1: Create a new billing request Pass the `customer_id` and `bank_account_id` to create a new billing request. ```http POST https://api.gocardless.com/billing_requests "billing_requests": { "mandate_request": { "currency": "GBP" // "scheme": "bacs" } "links": { "customer": "CU000176GQ2BXM" "bank_account": "BA123456789" } } ``` #### Step 2a: Create a Billing Request flow Since we already have the customer and bank_account the payer need not fill out the form. The payer only has to confirm the details. ```http POST https://api.gocardless.com/billing_request_flows { "billing_request_flows": { "auto_fulfil": true, "lock_bank_account": true, "lock_customer_details": true, "links": { "billing_request": "" } } } ``` #### Step 2b-1: For Custom payment pages (Using the Billing Request API) Confirm the customer and bank account details ```http POST https://api.gocardless.com/billing_requests/BR12345678/actions/confirm_payer_details ``` Fulfil the billing request ```http POST https://api.gocardless.com/billing_requests/BR12345678/actions/fulfil ``` #### Step 2b-2: For Custom payment pages (Using Direct Debit APIs) If you create mandates using the 3 endpoints - `customer create`, `bank account create` and `mandate create` Since the customer and bank_account are already available the merchant have to only create the mandate using `mandate create API` ```http POST https://api.gocardless.com/mandates HTTP/1.1 { "mandates": { "scheme": "bacs", "links": { "customer_bank_account": "BA123" } } } ``` > **Info:** > **Can the blocklist created by one organisation be used by another organisation?** A Blocklist is > created per organisation. For example, if an email is blocked by organisation A then the mandate > set up will be blocked if the payer is setting up the mandate for org A with this email. If the > same payer sets up the mandate using the same email for org B then this mandate creation will not > be blocked. ## What's next? ## Prefill Customer Details URL: https://docs.gocardless.com/docs/optimise/prefill-customer-details > Prefill customer details in billing requests. # Prefilling customer details If you already hold information about your customer (the payer), you can provide this information before sending your customer through a Billing Request Flow. As a result of prefilling customer data, the customer will need to perform fewer steps to complete their payment flow. This leads to a more seamless experience with less friction for the customer and will result in higher conversion. There are three ways that prefilling can be done. 1. **[Collect Customer Details](/docs/collect-payments/setting-up-mandates) endpoint** — Creates a fully pre-populated customer record so the customer skips the details page. Requires [GoCardless Pro](https://gocardless.com/pricing) or [GoCardless Enterprise](https://gocardless.com/pricing) with the [custom payment pages upgrade](https://support.gocardless.com/hc/en-gb/articles/115004521925-Custom-Payment-Pages). 2. **Existing customer record** — Link an existing customer ID to the Billing Request. The customer's details are already known and they skip the customer details page entirely. 3. **Billing Request Flows API** — Pass prefilled values into the Billing Request Flow. The customer sees their details pre-populated in the form and only needs to confirm them. This flowchart explains which of the above methods you would use for various situations: ![Billing Request Prefilling workflow choices](/images/docs/optimise/prefill-customer-details/br_prefilling_choices.png) This doc explains how to prefill customer details using each of these approaches before sending someone into a Billing Request Flow. > **Info:** > When customer details are captured on a billing request, GoCardless automatically shows an email > verification prompt when the authorisation link is opened. [See how Customer Email Check > works.](/docs/optimise/prefill-customer-details/customer-email-check) ## Create a Billing Request Create a Billing Request for whatever resources you want to create - our example will ask for a payment of £5. Omitting a customer ID means we'll create a new, blank customer linked against the request. Use the [Create a Billing Request](/docs/api-reference/billing-request#create-a-billing-request) endpoint: ```json POST /billing_requests { "billing_requests": { "payment_request": { "currency": "GBP", "amount": "500", "description": "Large pot of Marmalade" } } } ``` You will receive a full Billing Request, and the new customer and customer billing details will be linked against it. It will look like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": null, "payment_request": { "currency": "GBP", "amount": "500", "description": "Large pot of Marmalade" "scheme": "faster_payments" }, "links": { "customer": "CU00016VR36GVW", "customer_billing_detail": "CBD000010M15PAC" } } } ``` ## Provide details you wish to prefill If we know our customer's name is Paddington Bear, we can provide those details via the [Collect Customer Details](/docs/collect-payments/integration-planner) endpoint. Using the ID of the Billing Request we just created: ```json POST /billing_requests/BRQ123/actions/collect_customer_details { "data": { "customer": { "given_name": "Paddington", "family_name": "Bear", "email": "paddington@bearthings.com" }, "customer_billing_detail": { "address_line1": "32 Windsor Gardens", "city": "London", "postal_code": "W9 3RG", "country_code": "GB" } } } ``` This returns the Billing Request: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": null, "payment_request": { "description": "Large pot of Marmalade", "currency": "GBP", "amount": 500, "scheme": "faster_payments", "links": {}, "metadata": {} }, "links": { "customer": "CU00016VR36GVW", "customer_billing_detail": "CBD000010M15PAC" }, "actions": [ { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": [ "choose_currency" ], "status": "completed", "collect_customer_details": { "incomplete_fields": { "customer": [], "customer_billing_detail": [] } } }, ..., ], "resources": { "customer": { "id": "CU00016VR36GVW", "created_at": "2021-04-08T14:06:30.977Z", "email": "paddington@bearthings.com", "given_name": "Paddington", "family_name": "Bear", "company_name": null, "language": "en", "phone_number": null, "metadata": {} }, "customer_billing_detail": { "id": "CBD000010M15PAC", "created_at": "2021-04-08T14:06:30.997Z", "address_line1": "32 Windsor Gardens", "address_line2": null, "address_line3": null, "city": "London", "region": null, "postal_code": "W9 3RG", "country_code": "GB", "swedish_identity_number": null, "danish_identity_number": null } } } } ``` Note that the embedded customer resource contains the prefilled customer details that have been provided. Also note that the `collect_customer_details` action is in the `completed` state. ## Create a Billing Request Flow Create a Billing Request Flow to retrieve a link that can be provided to your customer to complete the request: ```json POST /billing_request_flows { "billing_request_flows": { "links": { "billing_request": "BRQ123" } } } ``` This returns the Billing Request Flow: ```json { "billing_request_flows": { "id": "BRF000012CV7SZN9ZJC3S27AAZ1JFWCW", "auto_fulfil": true, "redirect_uri": null, "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=BRF000012CV7SZN9ZJC3S27AAZ1JFWCW", "lock_customer_details": false, "lock_bank_account": false, "expires_at": "2021-05-14T15:34:44.693Z", "created_at": "2021-05-07T15:34:44.707Z", "links": { "billing_request": "BRQ123" } } } ``` If the customer visits the `authorisation_url`, they will will be taken directly to the bank select stage thus skipping the collect customer details step since this has been completed for them already. ## Final note It's worth noting that this same functionality means customers who leave the flow and come back later will resume from where they left off. ## What's next? #### [Prefill with Existing Customer](/docs/optimise/prefill-customer-details/existing-customers) Link an existing customer record to skip the customer details step entirely. #### [Prefill into Billing Request Flow](/docs/optimise/prefill-customer-details/billing-request-flow) Pass prefilled values directly into the checkout flow. ## Prevent Fraud with Protect+ URL: https://docs.gocardless.com/docs/optimise/prevent-fraud-with-protect-plus > Prevent fraud with GoCardless Protect+. # GoCardless Protect+ GoCardless Protect+ is our anti-fraud payment intelligence product. We have been processing bank debit payments for over a decade, giving us industry-leading payment intelligence data based on tens of billions of dollars worth of payments, including payments across 37 countries. Using this data we detect, verify, monitor, and challenge payers across the lifecycle of your payments. With GoCardless Protect+ you are able to: - detect suspected fraudulent payers using payment intelligence - use advanced open-banking functionality to verify suspected fraudulent payers, based on your risk profile - monitor fraudulent behaviour and its impact on your business - take actions against the suspected fraudulent payers such as challenging unfair chargebacks or blocking payers entirely All of this helps you stay one step ahead in the fight against payment fraud. ## Requirements In order to use Protect+, you must complete the below steps and ensure you have integrated with our Billing Request API, which offers our latest and most advanced features. > **Warning:** > You will not be able to use Protect+ features if you miss any of the below steps. ### Request the Protect+ upgrade **Merchants:** Your organisation must have both the Protect+ and Verified Mandates upgrades enabled. Please get in contact with our [support team](mailto:help@gocardless.com) to enable this. **Partners:** The upgrade needs to be enabled individually at the organisation level if any organisation connected or signed up using your app wants to use Protect+. You can do this by contacting our [support team](mailto:help@gocardless.com). ### Integrate with Billing Requests API **Merchants:** In order to use Protect+, you must be using the payment pages that are supported using [Billing Requests API](/docs/collect-payments/setting-up-mandates). You can use the payment pages in any of the below forms: - [Billing Request Flow - GC Hosted UI](/docs/collect-payments/setting-up-mandates/verified-mandates): Your payers will be redirected to the Billing Request flow if you are using any of [Billing Request Flow API](/docs/api-reference/billing-request-flow#create-a-billing-request-flow), [Billing Request Template](/docs/api-reference/billing-request-template), the [redirect flow API](/docs/api-reference/redirect-flow#create-a-redirect-flow), or adding customers using the authorisation link generated from the GC dashboard. - [Custom Payment Pages](/docs/collect-payments/setting-up-mandates/verified-mandates): Build your own integration with the Billing Requests API - [JavaScript Dropin](/docs/collect-payments/integration-types/javascript-drop-in-flow) **Partners:** You need to have one of the above integrations in place for the organisations connected to your app to start using and getting benefits from Protect+ features. ## Features Once you have completed the requirements, listed in the steps above, you will be able to benefit from the range of Protect+ features, available via the Billing Requests API and the merchant dashboard. ### API Features #### Verify risky payers using Verified Mandates With Protect+ you are able to reduce fraud by verifying payers that are deemed as potentially fraudulent. We use our Machine Learning capability to determine if a payer needs to be verified, due to their fraud risk, while they are going through one of the payment pages above. As part of the verification, payers will be asked to authenticate themselves by logging into their bank account, to prove their account ownership. You will need to set the `verify` preference to `recommended` when creating the Billing Request or Billing Request Template. The `recommended` setting will combine our Machine Learning with your custom Risk Setting options to determine which payers will be sent for bank authentication. > **Info:** > If no option is specified, `recommended` will be used by default. More information about verified mandates and the countries which support this can be found [here](/docs/collect-payments/setting-up-mandates/verified-mandates). > **Info:** > If you are a **Partner** then setting verify to `recommended` will: > > - verify the risky payers if the connected merchant **has the Protect+ upgrade** > - behave like `minimum` for the connected merchants **without the Protect+ upgrade** and verification will not be triggered ##### Billing Request: ```http POST https://api.gocardless.com/billing_requests HTTP/1.1 { "billing_requests": { "mandate_request": { "scheme": "bacs", "verify": "recommended" } } } ``` ##### Billing Request Template: ```http POST https://api.gocardless.com/billing_request_templates HTTP/1.1 { "billing_request_templates": { "mandate_request_scheme": "bacs", "mandate_request_verify": "recommended" "redirect_uri": "https://my-company.com/landing", } } ``` You can confirm that a payer has completed bank authorisation in three ways. Once complete: - the query parameter of either `outcome=success` or `outcome=failure` will be appended to the redirect_uri. If the bank authorisation has expired, the parameter will be set to `outcome=timeout`. The payer at this point can be prompted to try the bank authorisation step again (although this may be the result of a fraudulent payer being deterred). - responses through the mandate endpoints will contain the `verified_at` field with a timestamp of when the mandate was verified. - the mandate page will have its verification status displayed within the merchant dashboard: ![Protect+: Verified mandate](/images/docs/optimise/prevent-fraud-with-protect-plus/screenshot_2023-05-05_at_10.38.39.png) #### Blocks With Protect+, you are able to prevent certain customer details from being used when creating mandates. These include email domains, email addresses, and bank details. This feature can be accessed using the [API](/docs/api-reference/block#create-a-block) as well from the Blocklist page on the merchant dashboard (see below). ### Dashboard Features Under the Protect+ section of the merchant dashboard, you can access the below features. #### Risk Settings The Risk Settings page allows you to control the level of fraud prevention that is right for your business. We combine the risk score returned by our Machine Learning model with the Risk Setting you have configured on the merchant dashboard to determine if a payer should be sent for verification. A lower risk setting means fewer payers will be sent for verification checks, which could increase your exposure to fraud. On the other hand, a higher risk setting could impact conversion, which is why we have made it easy for you to specify the setting that matches your risk appetite. ![Protect+ Risk Setting Page](/images/docs/optimise/prevent-fraud-with-protect-plus/slider.png) #### Monitoring The Monitoring page allows you to: - Monitor the fraudulent activities affecting your account. This data will help you to decide which decisions to take to tackle fraud with the features offered by Protect+, such as challenging chargebacks, verifying payers, and blocking known fraudsters. - Easily visualise and understand the impact of Protect+ on your business. > **Info:** > If you are new to GoCardless, you may need to wait for your account to have at least two months of > data before you can see some of the metrics. ![Protect+ Monitoring Page](/images/docs/optimise/prevent-fraud-with-protect-plus/intro_-_monitoring.png) #### Chargebacks The Chargebacks page lists chargebacks by your customers, and allows you to challenge any which you believe have been unfairly charged back. In this section, you can upload the required evidence to support your challenge, as well as track the status of any challenged chargeback. ![Protect+ Chargeback page](/images/docs/optimise/prevent-fraud-with-protect-plus/intro_-_chargebacks.png) #### Blocklist The blocklist page enables you to block customers using certain details from setting up new mandates. You are able to block the email domain, email address, and bank details of suspected fraudsters. You can also use the mandate ID or customer ID to block the email address and bank account details linked to that customer. On the blocklist page, you can: - Create a block - List the items already blocked - Remove a block ![Blocklist page](/images/docs/optimise/prevent-fraud-with-protect-plus/blocklist.png) All blocked mandates can be viewed under the Events page of the merchant dashboard using the 'Blocked' filter for Mandates. ![Screenshot 2023-05-05 at 11.02.26](/images/docs/optimise/prevent-fraud-with-protect-plus/screenshot_2023-05-05_at_11.02.26.png) ## What's next? #### [Blocking Mandates](/docs/optimise/blocking-mandates) Learn how to block mandates from specific customers or details to prevent fraudulent activity. #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Use scenario simulators to test and validate your Protect+ integration in the sandbox environment. ## Reduced Failed Payments with Success+ URL: https://docs.gocardless.com/docs/optimise/reduced-failed-payments-with-success-plus > Reduce failed payments with intelligent payment retries. # Reduce failed payments with Success+ ## What is Success+ and what does it do? Success+ is a payment intelligence and automation product that uses machine learning to manage and reduce payment failures. When a payment fails, Success+ retries it on the date it's most likely to succeed, recovering on average 71% of failed payments. ## What payments does Success+ retry? Success+ will only retry payments that fail due to NSF (Non-sufficient funds). You can see a breakdown of reason codes below: | Scheme | Reason codes | | -------- | ------------ | | ACH | R01, R09 | | AutoGiro | TK82-1 | | BACS | 0 | | BECS | 6 | | BECS_NZ | AM04 | | PAD | 901 | | SEPA | AM04, MS03\* | _\*MS03 only applies to the following countries: Austria, Belgium, Germany, Luxembourg and Slovakia_ ## Good to Know Please ensure you are listening and making actionable changes to the `late_failure_settled` event, as this payment may also be eligible to be retried through Success+. A late failure is not a final state, depending on the reason code as shown above. For example, if a payment encounters a late failure due to non-sufficient funds, it is eligible to be retried through Success+. ## How to use Success+ ### Enabling Success+ Success+ is enabled via the [GoCardless dashboard](https://manage.gocardless.com/success-plus/intelligent-retries). > **Info:** > You must be an admin user to enable Success+. If for any reason you are not able to enable the > feature through the GoCardless dashboard, you will be prompted to contact our Sales or Support > team. 1. Log into the GoCardless dashboard and navigate to the Success+ page. Or follow the [link here](https://manage.gocardless.com/success-plus/intelligent-retries). 2. Click **Turn on Success+** 3. Choose the scheme/schemes you want to enable Success+ for 4. Choose the configuration that suits your business. We offer a default preset with the highest chance of recovery. 5. Click **Enable retries for…** to enable Success+ ## Using Success+ through API As mentioned above, the initial configuration for Success+ is done via the GoCardless dashboard, even if your business uses GoCardless via API. > **Info:** > If you are a Partner, you will need to track all events associated with a payment to provide > clarity around the current status and ultimate outcome. For example, tracking failed payments for > your customers and displaying a UI that showcases failed payments within a given period on the > customer profile. This information will be insightful for our joint customers in understanding > failed payment activity. API merchants do have the additional ability to decide whether Success+ should be applied on each payment they submit, via a boolean flag. This is useful if your business wants to create its own rules about when Success+ should apply to different customers or payment types. ### The Success+ flag The flag `retry_if_possible` is used to control whether Success+ is enabled on a payment. The following payment types support this boolean flag: - Individual payments - Instalment schedules - Subscriptions For API users enabling Success+, the flag is mandatory and by default, the flag will be set to `false`. If you are enabling Success+ as a partner, the flag will automatically be set to `true` unless specified otherwise. ### Using Success+ with individual payments _Creating payments_ When creating a payment, set `retry_if_possible` to `true`. This will enable intelligent retries if the payment is eligible. _Updating payments_ If a payment has been created with `retry_if_possible` set to `true`, then it can be [updated](/docs/api-reference/payment) to `false`. This will prevent the payment from being automatically retried in the event of a failure. > **Info:** > The API currently only allows the flag to be updated to false. Hence for a payment which has been > already created it is not possible to set this flag to true. ```http POST https://api.gocardless.com/payments HTTP/1.1 Content-Type: application/json { "payments": { "amount": 100, "currency": "GBP", "retry_if_possible": true, ... } } PUT https://api.gocardless.com/payments/PM123 HTTP/1.1 Content-Type: application/json { "payments": { "retry_if_possible": false } } ``` ### Using Success+ with Instalment Schedules When creating an [instalment schedule](/docs/api-reference/instalment-schedule#create-with-schedule) set `retry_if_possible` to true to ensure that all instalment payments created are automatically retried upon failure. ```http POST https://api.gocardless.com/instalment_schedules HTTP/1.1 Content-Type: application/json { "instalment_schedules": { "name": "Bike Invoice 271", "total_amount": "2500", "currency": "GBP", "retry_if_possible": true, ... } ``` ### Using Success+ with Subscriptions When creating a [subscription](/docs/api-reference/subscription#create-a-subscription) set `retry_if_possible` to true to ensure that all payments created for the subscription are retried automatically upon failure. ```http POST https://api.gocardless.com/subscriptions HTTP/1.1 Content-Type: application/json { "subscriptions": { "amount": "2500", "currency": "GBP", "interval_unit": "monthly", "retry_if_possible": true, ... } ``` ## Handling Failures On payment failure the `failed` [event](/docs/api-reference/events/payment) will always be sent. If the payment will be automatically retried the field `will_attempt_retry` will be `true`. When a payment is automatically retried it will trigger a `resubmission_requested` event just like any other type of retry. > **Warning:** > When `will_attempt_retry` is `true`, GoCardless will automatically retry the payment. Please do > not attempt to collect the payment from the customer yourself, as this can lead to them being > double charged. ```http GET https://api.gocardless.com/events/EV123 HTTP/1.1 HTTP/1.1 200 (OK) Content-Type: application/json { "events": { "id": "EV123", "created_at": "2014-04-08T17:01:06.000Z", "resource_type": "payments", "action": "failed", "details": { "origin": "bank", "cause": "insufficient_funds", "description": "The customer's account had insufficient funds to make this payment.", "scheme": "sepa_core", "reason_code": "AM04", "will_attempt_retry": true }, "metadata": {}, "links": { "payment": "PM123" } } } ``` ### What to do if a payment is going to be retried - After any `payment_failed` event with `will_attempt_retry` set to true, we will send a `payment:resubmission_requested` event. - You can treat this exactly the same as a manual user-triggered retry - the payment will be re-attempted on the new `charge_date` and will go through the normal payment flow. ### How to know which payments will be retried - You can use the `will_attempt_retry` flag on the `payment:failed` event to identify payments which will be intelligently retried. - If the flag is set to `true`, then the payment **will** be intelligently retried. - If set to `false`, the payment **will not** be retried and then you can [retry the payment manually](/docs/api-reference/payment#retry-a-payment). ### How to stop a payment being retried - To stop a payment from being retried, call the [update payment endpoint](/docs/api-reference/payment#update-a-payment) with `retry_if_possible` set to `false` - While the initial payment will still continue, it will **not** be automatically retried. - The payment status must be in "pending_submission" for it to be updated successfully ### When a payment will be retried > **Warning:** > The criteria below are subject to change and should not be relied upon. Use the > `will_attempt_retry` field in the `failed` event to know for sure if a payment will be retried. The `retry_if_possible` field does not guarantee the payment will be retried on failure. A payment will be retried if the following conditions are met: - Intelligent retries for the scheme has been enabled on the [settings page](https://manage.gocardless.com/success-plus). - The payment has field `retry_if_possible` set to true. - The payment has failed due to insufficient funds. - The number of payment failures is lesser than the number of retries configured in the intelligent retries settings page. - The subsequent retry can be confirmed within the retry window configured in the intelligent retries settings page. ## What's next? #### [Handling Webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) Learn how to receive and process webhook events to stay up to date with payment status changes. #### [Payments API Reference](/docs/api-reference/payment) Explore the full Payments API reference to manage payments, retries, and updates. ## Retain Customers with Fallbacks URL: https://docs.gocardless.com/docs/optimise/retain-customers-with-fallbacks > Retain customers by providing fallback payment methods. # Retain customers with Fallbacks > **Warning:** > **Fallbacks** should not be used if you are using > [Protect+](/docs/optimise/prevent-fraud-with-protect-plus) with Verified Mandates. Some customers may not be able to authorise the open banking transaction in the [Billing Request Flow](/docs/api-reference/billing-request-flow#create-a-billing-request-flow). A few reasons this can happen include but are not limited to, being unable to use their mobile, not being set up with online banking, or a transient issue with their bank's open banking API. To enable these customers to still complete the Billing Request via Direct Debit, create the Billing Request with the `fallback_enabled` parameter set to `true`. ## Create a Billing Request with Fallback Enabled > **Info:** > The option to pay via Direct Debit will only be shown if either the customer is unable to find > their banking institution in the select institution step, or there was some failure when they > attempt to authorise through their bank. [Create a Billing Request](/docs/api-reference/billing-request#create-a-billing-request) with the `fallback_enabled` parameter to `true`: ```json POST /billing_requests { "billing_requests": { "payment_request": { "currency": "GBP", "amount": "500", "description": "Large pot of Marmalade" }, "fallback_enabled": true } } ``` This will create a new Billing Request with the fallback option enabled. The response will look like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "payment_request": { "description": "Large pot of Marmalade", "currency": "GBP", "amount": 500, "scheme": "faster_payments", "links": {} }, "metadata": null, "links": { "customer": "CU123", "customer_billing_detail": "CBD123", "organisation": "OR123" }, "creditor_name": "Mr Creditor", "actions": [ { "type": "choose_currency", "required": true, "completes_actions": [], "requires_actions": [], "status": "completed" }, { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": ["choose_currency"], "status": "pending", "collect_customer_details": { "incomplete_fields": { "customer": ["email", "given_name", "family_name"] } } }, { "type": "select_institution", "required": false, "completes_actions": [], "requires_actions": [], "status": "pending" }, { "type": "collect_bank_account", "required": true, "completes_actions": ["choose_currency"], "requires_actions": [], "status": "pending" }, { "type": "bank_authorisation", "required": true, "completes_actions": [], "requires_actions": ["collect_bank_account"], "status": "pending" } ], "resources": { "customer": { "id": "CU123", "created_at": "2021-03-22T12:20:04.238Z", "email": null, "given_name": null, "family_name": null, "company_name": null, "language": "en", "phone_number": null, "metadata": {} }, "customer_billing_detail": { "id": "CBD123", "created_at": "2021-03-22T12:20:04.374Z", "address_line1": null, "address_line2": null, "address_line3": null, "city": null, "region": null, "postal_code": null, "country_code": null, "swedish_identity_number": null, "danish_identity_number": null } }, "fallback_enabled": true, "fallback_occurred": false } } ``` Customers attempting to complete this billing request will now have the option to complete it via Direct Debit, in the case that they cannot complete the regular open banking flow. ### The customer sees Continue payment using Direct Debit button This button is shown in two cases 1. Select Institution Screen 2. Bank Authorisation Failure #### Select Institution screen Customers will see an option to continue using Direct Debit when they search for their bank but can't find it. ![Billing Requests: Fallbacks - Select Institution screen](/images/docs/optimise/retain-customers-with-fallbacks/select_institution_screen.png) #### Bank Authorisation Failure The action is also shown in case of bank authorisation failure. To replicate this in the sandbox environment, you can select ![Billing Requests: Fallbacks - Select Fallback Institution screen](/images/docs/optimise/retain-customers-with-fallbacks/select_fallback_institution.png) Then you will proceed to the Bank Authorisation screen with the option to Continue Payment using Direct Debit. ![Billing Requests: Fallbacks - Bank Authorisation Failure Screen](/images/docs/optimise/retain-customers-with-fallbacks/bank_authorisation_failure.png) If the customer continues using Direct Debit, they will be shown the Collect Customer Details page in case if an address was not collected earlier. This is required for Direct Debit. ![Billing Requests: Fallbacks - Collect Customer Details Screen](/images/docs/optimise/retain-customers-with-fallbacks/collect_customer_details.png) Once the customer fills and confirms the details, they'll be shown the success screen confirming that Direct Debit has been set up and payment will be collected as soon as possible. ![Billing Requests: Fallbacks - Confirm Details Screen](/images/docs/optimise/retain-customers-with-fallbacks/confirm_details.png) ![Billing Requests: Fallbacks - Direct Debit Setup Success Screen](/images/docs/optimise/retain-customers-with-fallbacks/direct_debit_setup.png) Once the fallback occurs, then the `fallback_occurred` the parameter will be set to `true`. ## What's next? #### [Protect+](/docs/optimise/prevent-fraud-with-protect-plus) Learn how Protect+ uses payment intelligence to detect and prevent fraudulent payers. #### [Billing Requests](/docs/api-reference/billing-request) Explore the full Billing Requests API reference to build and customise your payment flows. ## Customer Email Check URL: https://docs.gocardless.com/docs/optimise/prefill-customer-details/customer-email-check > How GoCardless verifies payer identity when customer details are captured on a billing request. # Customer Email Check When a billing request has customer details captured — via a linked customer record, prefilled data, or a payer who has already started the flow — GoCardless shows an email verification prompt when the authorisation link is opened. This prevents a common issue where merchants mix reusable payment links with individual authorisation links, causing customers to inadvertently complete someone else's billing request. ## How it works When the authorisation link is opened: 1. The payer is prompted to enter their email address. 2. **If the email matches** the captured email — the payer proceeds with the current billing request flow. 3. **If the email does not match** — GoCardless attempts to generate a new authorisation link (possible when the billing request was created from a pay link or plan link) and redirects the payer to a new, empty flow. 4. **If a new link cannot be generated** — an error page is shown. If no customer details are captured on the billing request, the email check is skipped and the flow proceeds as normal. ## Happy path: email matches The payer enters the email matching the captured one and proceeds with the existing flow. ![Customer Email Check: Submit the email matching the captured one](/images/docs/optimise/prefill-customer-details/customer-email-check/screenshot_2023-11-27_at_08.30.47.png) ![Customer Email Check: Resume flow when email matches](/images/docs/optimise/prefill-customer-details/customer-email-check/screenshot_2023-11-27_at_08.31.46.png) ## Happy path: new flow generated The payer enters an email that does not match. GoCardless generates a new authorisation link and redirects the payer to a fresh, empty flow. This is possible when the billing request was created from a pay link or a plan link. ![Customer Email Check: Submit the email which does not match the captured one](/images/docs/optimise/prefill-customer-details/customer-email-check/screenshot_2023-11-27_at_08.38.31.png) ![Customer Email Check: Create a new flow when emails don't match](/images/docs/optimise/prefill-customer-details/customer-email-check/screenshot_2023-11-27_at_08.42.23.png) ## Unhappy path: new flow cannot be generated The payer enters a non-matching email but the billing request was not created from a pay link or plan link — so a new link cannot be generated automatically. An error page is displayed. ![Customer Email Check: Submit the email which does not match the captured one](/images/docs/optimise/prefill-customer-details/customer-email-check/screenshot_2023-11-27_at_08.38.31.png) ![Customer Email Check: Error when emails don't match and new link cannot be generated](/images/docs/optimise/prefill-customer-details/customer-email-check/screenshot_2023-11-27_at_08.39.30.png) ## What's next? #### [Prefill customer details](/docs/optimise/prefill-customer-details) Learn how to prefill customer details on billing requests to trigger the email check. #### [Billing Requests](/docs/collect-payments/setting-up-mandates) Set up mandates using Billing Requests. ## Prefilling Billing Request Flow URL: https://docs.gocardless.com/docs/optimise/prefill-customer-details/billing-request-flow > Prefill the billing request flow. # Prefilling customer details into Billing Request Flow If you already hold information about your customer (the payer), you can provide this information before sending your customer through a Billing Request Flow. As a result of prefilling customer data, the customer will need to perform fewer steps to complete their payment flow. This leads to a more seamless experience with less friction for the customer and will result in higher conversion. There are three ways that prefilling can be done. 1. **[Collect Customer Details](/docs/collect-payments/setting-up-mandates) endpoint** — Creates a fully pre-populated customer record so the customer skips the details page. Requires [GoCardless Pro](https://gocardless.com/pricing) or [GoCardless Enterprise](https://gocardless.com/pricing) with the [custom payment pages upgrade](https://support.gocardless.com/hc/en-gb/articles/115004521925-Custom-Payment-Pages). 2. **Existing customer record** — Link an existing customer ID to the Billing Request. The customer's details are already known and they skip the customer details page entirely. 3. **Billing Request Flows API** — Pass prefilled values into the Billing Request Flow. The customer sees their details pre-populated in the form and only needs to confirm them. This flowchart explains which of the above methods you would use for various situations: ![Billing Request Prefilling workflow choices](/images/docs/optimise/prefill-customer-details/br_prefilling_choices.png) This doc explains how to prefill customer details using each of these approaches before sending someone into a Billing Request Flow. > **Info:** > When customer details are captured on a billing request, GoCardless automatically shows an email > verification prompt when the authorisation link is opened. [See how Customer Email Check > works.](/docs/optimise/prefill-customer-details/customer-email-check) ## Create a Billing Request Create a Billing Request for whatever resources you want to create - our example will ask for a payment of £5. Omitting a customer ID means we'll create a new, blank customer linked against the request. Use the [Create a Billing Request](/docs/api-reference/billing-request#create-a-billing-request) endpoint: ```json POST /billing_requests { "billing_requests": { "payment_request": { "currency": "GBP", "amount": "500", "description": "Large pot of Marmalade" } } } ``` You will receive a full Billing Request. This will contain new customer and customer billing details linked against it which are empty. It will look like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": null, "payment_request": { "currency": "GBP", "amount": "500", "description": "Large pot of Marmalade" "scheme": "faster_payments" }, "links": { "customer": "CU00016VR36GVW", "customer_billing_detail": "CBD000010M15PAC" } } } ``` ## Create a Billing Request Flow With Prefilled Customer Details Create a Billing Request Flow to retrieve a link that can be provided to your customer to complete the request. Provide prefilled customer details in this request: ```json POST /billing_request_flows { "prefilled_customer": { "given_name": "Paddington", "family_name": "Bear", "email": "paddington.bear@acmeplc.com" }, "links": { "billing_request": "BRQ123" } } } ``` This returns the Billing Request Flow: ```json { "billing_request_flows": { "id": "BRF000012CV7SZN9ZJC3S27AAZ1JFWCW", "auto_fulfil": true, "redirect_uri": null, "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=BRF000012CV7SZN9ZJC3S27AAZ1JFWCW", "lock_customer_details": false, "lock_bank_account": false, "expires_at": "2021-05-14T15:34:44.693Z", "created_at": "2021-05-07T15:34:44.707Z", "links": { "billing_request": "BRQ123" } } } ``` If the customer visits the `authorisation_url`, they will begin the checkout flow asking for their customer details, but with given and family name already prefilled: ![Prefilled Billing Request Flow Form](/images/docs/optimise/prefill-customer-details/billing-request-flow/screenshot_2022-08-10_at_15.59.42.png) The customer can amend any of the prefilled information and complete those fields that haven't been prefilled. ## Final note It's worth noting that this same functionality means customers who leave the flow and come back later will resume from where they left off. ## What's next? #### [Prefilling Overview](/docs/optimise/prefill-customer-details) Compare all three prefilling approaches. #### [Billing Requests API Reference](/docs/api-reference/billing-request) Full reference for the Billing Requests API. ## Prefilling Existing Customer Details URL: https://docs.gocardless.com/docs/optimise/prefill-customer-details/existing-customers > Prefill details for existing customers. # Prefilling customer details with existing customer record If you already hold information about your customer (the payer), you can provide this information before sending your customer through a Billing Request Flow. As a result of prefilling customer data, the customer will need to perform fewer steps to complete their payment flow. This leads to a more seamless experience with less friction for the customer and will result in higher conversion. There are three ways that prefilling can be done. 1. **[Collect Customer Details](/docs/collect-payments/setting-up-mandates) endpoint** — Creates a fully pre-populated customer record so the customer skips the details page. Requires [GoCardless Pro](https://gocardless.com/pricing) or [GoCardless Enterprise](https://gocardless.com/pricing) with the [custom payment pages upgrade](https://support.gocardless.com/hc/en-gb/articles/115004521925-Custom-Payment-Pages). 2. **Existing customer record** — Link an existing customer ID to the Billing Request. The customer's details are already known and they skip the customer details page entirely. 3. **Billing Request Flows API** — Pass prefilled values into the Billing Request Flow. The customer sees their details pre-populated in the form and only needs to confirm them. This flowchart explains which of the above methods you would use for various situations: ![Billing Request Prefilling workflow choices](/images/docs/optimise/prefill-customer-details/br_prefilling_choices.png) This doc explains how to prefill customer details using each of these approaches before sending someone into a Billing Request Flow. > **Info:** > When customer details are captured on a billing request, GoCardless automatically shows an email > verification prompt when the authorisation link is opened. [See how Customer Email Check > works.](/docs/optimise/prefill-customer-details/customer-email-check) ## Create a Billing Request Create a Billing Request for whatever resources you want to create - our example will ask for a payment of £5. Supply the ID of an existing customer record via the `links[customer]` field in o apply it to the Billing Request. Use the [Create a Billing Request](/docs/api-reference/billing-request#create-a-billing-request) endpoint: ```json POST /billing_requests { "billing_requests": { "payment_request": { "currency": "GBP", "amount": "500", "description": "Large pot of Marmalade" } }, "links": { "customer": "CU00016YYBRCJD" } } ``` You will receive a full Billing Request, and the existing customer and customer billing details will be linked against it. It will look like this: ```json { "billing_requests": { "id": "BRQ123", "status": "pending", "mandate_request": null, "payment_request": { "description": "Large pot of Marmalade", "currency": "GBP", "amount": 500, "scheme": "faster_payments", }, "actions": [ { "type": "collect_customer_details", "required": true, "completes_actions": [], "requires_actions": [ "choose_currency" ], "status": "pending", "collect_customer_details": { "incomplete_fields": { "customer": [ "email" ], "customer_billing_detail": [] } } }, ... ], "resources": { "customer": { "id": "CU00016YYBRCJD", "created_at": "2021-05-07T15:34:38.627Z", "email": null, "given_name": "Paddington", "family_name": "Bear", "company_name": null, "language": "en", "phone_number": null, "metadata": {} } } } } ``` ## Create a Billing Request Flow You can now proceed to create a Billing Request Flow to retrieve a link that can be provided to your customer to complete the request: ```json POST /billing_request_flows { "billing_request_flows": { "links": { "billing_request": "BRQ123" } } } ``` This returns the Billing Request Flow: ```json { "billing_request_flows": { "id": "BRF000012CV7SZN9ZJC3S27AAZ1JFWCW", "auto_fulfil": true, "redirect_uri": null, "authorisation_url": "https://pay.gocardless.com/billing/static/flow?id=BRF000012CV7SZN9ZJC3S27AAZ1JFWCW", "lock_customer_details": false, "lock_bank_account": false, "expires_at": "2021-05-14T15:34:44.693Z", "created_at": "2021-05-07T15:34:44.707Z", "links": { "billing_request": "BRQ123" } } } ``` If the customer visits the `authorisation_url`, they will begin the checkout flow asking for their customer details, but with given and family name already prefilled: ![Pre-filled Customer Details Form](/images/docs/optimise/prefill-customer-details/existing-customers/prefilled-form.png) The customer can amend any of the prefilled information and complete those fields that haven't been prefilled. ## Final note It's worth noting that this same functionality means customers who leave the flow and come back later will resume from where they left off. ## What's next? #### [Prefilling Overview](/docs/optimise/prefill-customer-details) Compare all three prefilling approaches. #### [Retain Customers with Fallbacks](/docs/optimise/retain-customers-with-fallbacks) Offer a fallback payment method when bank authorisation fails. --- # GoCardless Embed ## Introduction URL: https://docs.gocardless.com/docs/gc-embed > Introduction to GoCardless Embed for platforms. # GoCardless Embed ## Introduction GoCardless Embed allows you to offer white-labelled bank payments to your merchants. This guide walks through how to integrate with GoCardless' API in order to access our global bank pay network. You can follow this guide along with the [GoCardless Embed Postman collection](https://www.postman.com/gocardlessapi/workspace/gocardless-api/folder/22460459-a63ee809-9a35-4eaa-a689-3e9fb3b5dd91?ctx=documentation). ## Contents This guide will cover: - Creating creditors to represent each of your merchants. - Adding creditor bank accounts where GoCardless will settle funds. - Requesting scheme identifiers to customise the beneficiary name on the payer's bank statement. - Using Billing Requests to set up mandates and collect payments. - Handling webhooks to keep track of event actions and trigger notifications to payers. - Reconciling payments to keep track of the entire flow of funds. ## Prerequisites Before starting this guide you should: - Contact the[ GoCardless Embed team](https://get.gocardless.com/l/1118633/2026-03-26/skf8xj) so we can set up a sandbox account for you. - Once you have access to your account, create a read-write API token in the dashboard and use it to make a request. Follow [making your first request](/docs/getting-started/send-your-first-api-request) for how to do this. ## What's next? #### [Creating a Creditor](/docs/gc-embed/creating-a-creditor) Create a creditor to represent each of your merchants and enable per-merchant payouts and reconciliation. #### [API Reference](/docs/api-reference) Full reference documentation for the GoCardless API. ## Adding a Creditor Bank Account URL: https://docs.gocardless.com/docs/gc-embed/adding-a-creditor-bank-account > Add a creditor bank account (optional). # Adding a Creditor Bank Account > **Info:** > Adding a creditor bank account is optional. If you do not create a creditor bank account funds > will be settled to your default payout bank account. In this step of the GoCardless Embed guide you will create a creditor bank account for the creditor you created in the previous step. The creditor bank account is where GoCardless will settle the funds we collect from the creditor's payers. This bank account must be controlled by you and **not**be the merchant's bank account. GoCardless will only pay out once we have verified you control the bank account. You should add a creditor bank account for each currency you collect so GoCardless can pay out in that currency. ## POST /creditor_bank_accounts You can create a creditor bank account by performing a POST request to the `/creditor_bank_accounts` endpoint. The required parameters depend on the country. For a French bank account they are: | Parameter | Description | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | country_code | The country that the bank account is registered in, as a [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). | | currency | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently `EUR`, `GBP`, and `USD` are supported for the GoCardless Embed product. | | account_holder_name | Name of the account holder, as known by the bank. This must be an account owned by you and **not**the merchant. | | iban | International Bank Account Number. Alternatively you can provide [local details](/docs/api-reference/local-bank-details). | | links[creditor] | The ID of the creditor whose payments should be paid out to this account. | Examples of how to make this request using the GoCardless [client libraries](/docs/developer-resources/client-libraries): ```http POST https://api.gocardless.com/creditor_bank_accounts HTTP/1.1 Content-Type: application/json { "creditor_bank_accounts": { "account_number": "55779911", "branch_code": "200000", "country_code": "GB", "account_holder_name": "Nude Wines", "links": { "creditor": "CR123" } } } HTTP/1.1 201 Created Location: /creditor_bank_accounts/BA123 Content-Type: application/json { "creditor_bank_accounts": { "id": "BA123", "created_at": "2014-05-27T12:43:17.000Z", "account_holder_name": "Nude Wines", "account_number_ending": "11", "account_type": null, "country_code": "GB", "currency": "GBP", "bank_name": "BARCLAYS BANK PLC", "enabled": true, "verification_status": "pending", "links": { "creditor": "CR123" } } } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/creditor_bank_accounts" \ -d @- << EOF { "creditor_bank_accounts": { "account_number": "55779911", "branch_code": "200000", "country_code": "GB", "account_holder_name": "Nude Wines", "links": { "creditor": "CR123" } } } EOF ``` ```php $client->creditorBankAccounts()->create([ "params" => [ "account_number" => "55779911", "branch_code" => "200000", "country_code" => "GB", "account_holder_name" => "Nude Wines", "links" => [ "creditor" => "CR123" ] ] ]); ``` ```python client.creditor_bank_accounts.create(params={ "account_number": "55779911", "branch_code": "200000", "country_code": "GB", "account_holder_name": "Nude Wines", "links": { "creditor": "CR123" } }) ``` ```ruby @client.creditor_bank_accounts.create( params: { account_holder_name: "Example Ltd", account_number: "55779911", branch_code: "200000", country_code: "GB", links: { creditor: "CR123" } } ) ``` ```java CreditorBankAccount creditorBankAccount = client.creditorBankAccounts().create() .withAccountNumber("55779911") .withBranchCode("200000") .withCountryCode("GB") .withAccountHolderName("Nude Wines") .withLinksCreditor("CR123") .execute(); ``` ```javascript const creditorBankAccount = await client.creditorBankAccounts.create({ account_number: "55779911", branch_code: "200000", country_code: "GB", account_holder_name: "Nude Wines", links: { creditor: "CR123", }, }); ``` ```net var creditorBankAccountRequest = new GoCardless.Services.CreditorBankAccountCreateRequest() { AccountHolderName = "Example Ltd", AccountNumber = "55779911", BranchCode = "200000", CountryCode = "GB", SetAsDefaultPayoutAccount = true, Links = new GoCardless.Services.CreditorBankAccountCreateRequest.CreditorBankAccountLinks() { Creditor = "CR0123" } }; var creditorBankAccountResponse = await gocardless.CreditorBankAccounts.CreateAsync(creditorBankAccountRequest); GoCardless.Resources.CreditorBankAccount creditorBankAccount = creditorBankAccountResponse.CreditorBankAccount; ``` ```go package main import ( gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } creditorBankAccountCreateParams := gocardless.CreditorBankAccountCreateParams{ AccountNumber: "55779911", BranchCode: "200000", CountryCode: "GB", AccountHolderName: "Nude Wines", } creditorBankAccount, err := client.CreditorBankAccounts.Create(context, creditorBankAccountCreateParams) ``` For more details, see the API [reference docs for creating creditor bank accounts](/docs/api-reference/creditor-bank-account#create-a-creditor-bank-account). ## Verify your bank account Once you have added a creditor bank account, you will see that the bank account `verification_status` will be in `pending` state. You will receive an email with details about how to verify your bank account which requires you to make a verification payment to us. You **must verify your bank account** in order to start receiving payouts. Once you have submitted the verification payment, you can check on the verification progress via the [GET /creditor_bank_accounts/BA123](/docs/api-reference/creditor-bank-account#get-a-single-creditor-bank-account) API. The `verification_status` will move to `in_review` state while we verify your account. Once your bank account has been verified, the `verification_status` will be in `successful` state and you will be able to start receiving payouts to that bank account. ## What's next? #### [Setting a Scheme Identifier](/docs/gc-embed/setting-a-scheme-identifier) Request a custom scheme identifier so your merchant's name appears on payers' bank statements. #### [Setting Up Mandates & Payments](/docs/gc-embed/setting-up-mandates-collecting-payments) Use Billing Requests to set up Direct Debit mandates and collect payments. ## API Request Signing URL: https://docs.gocardless.com/docs/gc-embed/api-request-signing > Sign API requests for GoCardless Embed (optional). # API Request Signing > **Info:** > API request signing is an optional opt-in feature for GoCardless Embed. To enable it, contact your > account manager. When enabled, API request signing works identically to the [outbound payments implementation](/docs/send-money/api-request-signing) — the same RFC-9421 mechanism, the same key generation steps, and the same code examples apply. The only difference is where you upload your public key in the dashboard: - Go to [Settings → Configurations](https://manage-sandbox.gocardless.com/company/configurations). - Under **API Request Keys**, add a new public key. See [API Request Signing](/docs/send-money/api-request-signing) for the full implementation guide. ## What's next? #### [Bank Details Access](/docs/gc-embed/bank-details-access) Access encrypted customer bank account details using RSA key encryption. #### [API Reference](/docs/api-reference) Full reference documentation for all GoCardless API endpoints. ## Bank Details Access URL: https://docs.gocardless.com/docs/gc-embed/bank-details-access > Access bank details in GoCardless Embed (optional). # Bank Details Access > **Info:** > To opt-in to bank details access, please contact your account manager to enable this upgrade. The `/bank_account_details` endpoint allows you to access encrypted bank account details by bank account identifier. This document outlines the steps required to retrieve customer bank account details. The process consists of two key steps: 1. **One-Time Public Key Setup:** Generate your public/private key pair and upload your public key in the GoCardless dashboard. This setup is a one-time action. 2. **Retrieving Bank Account Details:** Use the GoCardless API to retrieve encrypted bank account details and decrypt the response to get the customer's plaintext bank details. ## Public Key Setup The public key provided to GoCardless, must be an RSA 2048 bit key. This will be used to encrypt the symmetric encryption key using the OAEP padding scheme. Please follow the steps outlined below to generate your public/private key pair and add your public key in the GoCardless dashboard. ### Generating your key pair 1. Generate an RSA-2048 public/private key pair ```bash openssl genrsa -out privatekey.pem 2048 openssl rsa -in privatekey.pem -pubout -out publickey.pem ``` 2. Securely store your private key 3. Copy your public key PEM ### Upload your public key To make your public key available to GoCardless you will need to upload your public key in the dashboard: 1. Go to[ Developers](https://manage.gocardless.com/developers). 2. Under **Create** 1. Click **Public Key** 3. Click **Add public key** 1. Enter a **Name** - This will help you to identify your public key in the dashboard 4. Enter your **Public key** - Paste your generated public key PEM into the input box 5. Click **Add** 6. **Copy** **and save **the generated **Key ID** - You will need to use this ID to tell GoCardless which public key to use to encrypt data when making requests to the `/bank_account_details` endpoint 7. Click **Continue** > **Info:** > You can revoke a public key at any time by deleting it from the [Public > Keys](https://manage.gocardless.com/developers/public-keys) page. ## Steps to Retrieve Bank Details You can retrieve customer bank account details by: - providing any [customer bank account ID](/docs/api-reference/customer-bank-account) to the **/bank_account_details** API - including the public key ID you saved earlier as a request header `GC-Key-Id: PK123` If you want to retrieve customer bank details after they have completed a billing request, you can use the [webhook notification](/docs/gc-embed/handling-webhooks) GoCardless sends upon fulfilment of a billing request to retrieve the bank details by following these steps: 1. Get the bank account identifier from the fulfilment webhook - You will find this in `links.customer_bank_account` of the fulfilled billing request object 2. Send a request to the bank account details endpoint\*\* **using the customer bank account identifier - **GET /bank_account_details/\\*\* ```json REQUEST GET /bank_account_details/BA123 HEADERS - Gc-Key-Id (required): the key ID of your uploaded public key to use for encryption. RESPONSES success - 200: return payload containing encrypted bank details: { bank_account_details: } error - 403: integrator doesn't have the required feature enabled: - Forbidden request error - 404: bank account doesn't exist: - Resource not found error - 422: failure to fetch or encrypt the bank details: - Ensure your Gc-Key-Id header contains a valid public key ID ``` ### Decrypting bank details The response body from the **/bank_account_details** endpoint will contain an encrypted payload following [Json Web Encryption (JWE) standards described in RFC7516.](https://www.rfc-editor.org/rfc/rfc7516) The JWE Flattened format payload follows the structure shown in the example below and all values including the nested json header are base64 URL safe encoded. Example response body from `/bank_account_details/\`: ```json { "bank_account_details": { "protected": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJraWQiOiJiY2RkNDkzMmZhNjMxODY0MjI3YjhkZDZiMDdkMjQ5MDgyOGEzYWQ5OWM1OWMxNzc3ZDBjZTMzMDUyYjk5OGFiIn0", "encrypted_key": "pEQHNX_jCjKLIhZMa27C8cXgIlu7qUdrEcEuRwQw9EZyA_3vHG99gdd7YGQapVbSGEG43Hg5gi33Sgjsuekw6CumRFoBIKR7mANj5LUgfy6jFVFAC98RMiJ2H8yTBJlRiLonPRBILStNI8F7VU7cqqOOuCn7yeoeiJ7buSkqDW_ds9wrPC3uJgLZGyxPLU81R2WrE6b7hLVCpShLCBzH76wL3cPD5nYNT3eb5vqGl8SMb_mecZ-UnE5wfAzZhbU1CJ4qtlgFFiMt6HLFPvVAJBHlPdZaFcKotSjhOhk1rsySLrwKG9HmIBLykhED251jiIOyxTXIlNCzSMs23_R4XA", "iv": "6H4MLnhZGnwaWlQ2", "ciphertext": "Cntt_wZlkK4Ui7xI-BtAqf9V-FF41Cz8RxJd5KUGQJac", "tag": "WoaSncwUeLfU3IjgeFYtSQ" } } ``` The bank account details are encrypted using hybrid encryption, combining RSA and AES algorithms. The JWE payload includes a symmetric AES key, encrypted using your RSA public key, and a ciphertext, encrypted using the symmetric key. Nested JWE payload properties explained: | Key | Value | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | protected | Protected header values, including: `alg`: the asymmetric encryption type used to encrypt the symmetric key `enc`: the symmetric encryption type used to encrypt the actual content (bank details) `kid`: key ID of the public key used for asymmetric encryption The strings included in the protected header follow the standard set in RFC7518 for `alg` values and `enc` values. | | encrypted_key | Random symmetric key, encrypted with your public key. The symmetric key generated for each request will be an AES 256 bit key, used to encrypt the data in Galois/Counter Mode (GCM). | | iv | Initialisation vector - an arbitrary random number for seeding encryption. | | ciphertext | Actual data (bank details) encrypted with the symmetric key | | tag | Value to be recomputed on decrypt to validate the authenticity of the payload | #### Decryption Overview The process to decrypt the received payload will consist of the following broad steps - Use the `public_key_id` to verify the identity of your key pair - Use your private key to decrypt the `encrypted_key` - Use the now decrypted `encryption_key` to decrypt the `ciphertext` #### Detailed Decryption Steps Many widely available public libraries exist to handle JSON Object Signing and Encryption (JOSE), and will be able to decrypt the response. You can also choose to handle decryption yourself. > **Warning:** > Before implementing the decryption yourself, there are two points you need to be aware of: > > - In most implementations, the decryption operation will infer the correct cryptographic methods (in our case RSA-OAEP and A256GCM) from the protected header values. > - Authenticated methods such as GCM also make use of Additional Authenticated Data (AAD) which is used to compute the tag value in a JWE payload — by default the protected header is included as AAD by the JOSE library used in the following example which follows recommendations in the RFC specification. The following is an example of how you could use a [Javascript JOSE library](https://github.com/panva/jose) to decrypt bank details: ```javascript /** * Decryption method * @param responseBody response body from /bank_account_details * @param privateKeyPEM PEM-encoded private key string * @param keyId key ID of the public JWK you expect GoCardless to have encrypted the response with */ async function decrypt(responseBody, privateKeyPEM, keyId) { const private_key = await jose.importPKCS8(privateKeyPEM, "RSA-OAEP"); // Isolate JWE payload const JwePayload = responseBody["bank_account_details"]; // Extract protected header contents, to verify the keyID matches. // NOTE: The Base64 encoded contents of the protected header is also used during // encryption as the Additional Authenticated Data (AAD), most libraries, including // jose, will include the protected header as AAD to be authenticated on // decryption automatically const protectedHeader = jose.decodeProtectedHeader(JwePayload); if (protectedHeader.kid !== keyId) throw new Error("Incorrect key id: " + keyId); // Decrypt data with the private key. const { plaintext } = await jose.flattenedDecrypt(JwePayload, private_key); // Decode the decrypted data. const decoder = new TextDecoder(); // Pretty print the plaintext data. console.log(JSON.stringify(JSON.parse(decoder.decode(plaintext)), null, 2)); } ``` The following is an example of how you could handle decryption without a JOSE library, in Ruby using OpenSSL: ```ruby # response_body: GET /bank_account_details response body # private_key_pem: your private key PEM-encoded string # kid: the key ID of the public JWK you expect GoCardless to have encrypted the response with def decrypt(response_body:, private_key_pem:, kid:) # decode the response body jwe_payload = Hash[ response_body["bank_account_details"].map do |key, value| [key, Base64.urlsafe_decode64(value)] end] # parse the protected_header protected_header = JSON.parse(jwe_payload["protected"]) key_management_algorithm = protected_header["alg"] content_encryption_algorithm = protected_header["enc"] # check if protected_header kid matches expected kid raise StandardError if protected_header["kid"] != kid private_key = OpenSSL::PKey.read(private_key_pem) # decrypt the symmetric key content_encryption_key = private_key.private_decrypt(jwe_payload["encrypted_key"], padding_value(key_management_algorithm)) # instantiate a cipher and set the algorithm type to that contained in the jwe protected header's "enc" value decipher = OpenSSL::Cipher.new(cipher_value(content_encryption_algorithm)) decipher.decrypt # set cipher to decryption mode decipher.key = content_encryption_key decipher.iv = jwe_payload["iv"] decipher.auth_data = Utils.b64_encode(JSON.generate(protected_header)) decipher.auth_tag = jwe_payload["tag"] plaintext = decipher.update(jwe_payload["ciphertext"]) + decipher.final JSON.parse(plaintext) # => should return the decrypted object containing either local bank account details or an IBAN end ``` #### Interpreting the decrypted bank details The decrypted bank details will be in [IBAN](/docs/api-reference/local-bank-details) format in countries where IBAN is supported, or the [local bank details](/docs/api-reference/local-bank-details) otherwise. IBAN format: ```json { "iban": "..." } ``` Local bank details format: ```json { "bank_code": "...", "branch_code": "...", "account_number": "..." } ``` ## What's next? #### [API Reference](/docs/api-reference) Full reference documentation for all GoCardless API endpoints. #### [Go Live](https://get.gocardless.com/l/1118633/2026-03-26/skf8xj) Ready to launch? Contact the GoCardless Embed team to take your integration live. ## Creating a Creditor URL: https://docs.gocardless.com/docs/gc-embed/creating-a-creditor > Create a creditor for your GoCardless Embed integration. # Creating a Creditor In this step of the GoCardless Embed guide you will create a creditor to represent one of your merchants. By having a creditor for each merchant you will be able to pay out separately for each creditor, customise the beneficiary name the payer sees, and perform reconciliation on a per-merchant basis. ## POST /creditors You can create a creditor by performing a POST request to the `/creditors` endpoint. The required parameters are: | Parameter | Description | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | name | The trading name of the creditor. | | creditor_type | The type of business of the creditor. One of: `individual`, `company`, `charity`, `partnership`, and `trust`. | | country_code | The country that the creditor is registered in, as a [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). | Examples of how to make this request using the GoCardless [client libraries](/docs/developer-resources/client-libraries): ```http POST https://api.gocardless.com/creditors HTTP/1.1 Content-Type: application/json { "creditors": { "name": "Example Ltd", "country_code": "GB", "creditor_type": "company" } } HTTP/1.1 201 Created Location: /creditors/CR123 Content-Type: application/json { "creditors": { "id": "CR123", "created_at": "2017-02-16T12:34:56.000Z", "name": "Example Ltd", "creditor_type": "company", "country_code": "GB", ... } } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/creditors" \ -d @- << EOF { "creditors": { "name": "Example Ltd", "country_code": "GB", "creditor_type": "company" } } EOF ``` ```php $client = new \GoCardlessPro\Client([ 'access_token' => 'your_access_token_here', 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $client->creditors()->create([ 'params' => [ 'name' => 'Example Ltd', 'country_code' => 'GB', 'creditor_type' => 'company' ] ]); ``` ```python import gocardless_pro client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox') client.creditors.create(params={ "name": "Example Ltd", "country_code": "GB", "creditor_type": "company" }) ``` ```ruby @client = GoCardlessPro::Client.new( access_token: "your_access_token", environment: :sandbox ) @client.creditors.create( params: { name: "Example Ltd", country_code: "GB", creditor_type: "company" } ) ``` ```java import static com.gocardless.GoCardlessClient.Environment.SANDBOX; String accessToken = "your_access_token_here"; GoCardlessClient client = GoCardlessClient .newBuilder(accessToken) .withEnvironment(SANDBOX) .build(); Creditor creditor = client.creditors().create() .withName("Example Ltd") .withCountryCode("GB") .withCreditorType("company") .execute(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const gocardless = require("gocardless-nodejs"); const client = gocardless("your_access_token_here", constants.Environments.Sandbox); const creditor = await client.creditors.create({ name: "Example Ltd", country_code: "GB", creditor_type: "company", }); ``` ```net String accessToken = "your_access_token"; GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX); var creditorRequest = new GoCardless.Services.CreditorCreateRequest() { Name = "Example Ltd", CountryCode = "GB", CreditorType = "company", }; var creditorResponse = await gocardless.Creditors.CreateAsync(creditorRequest); GoCardless.Resources.Creditor creditor = creditorResponse.Creditor; ``` ```go package main import ( gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } creditorCreateParams := gocardless.CreditorCreateParams{ Name: "Example Ltd", CountryCode: "GB", CreditorType: "company", } creditor, err := client.Creditors.Create(context, creditorCreateParams) ``` The API will respond with a creditor object containing a creditor ID starting with 'CR'. This ID will be used in subsequent steps. For more details, see the [API reference docs for this endpoint](/docs/api-reference/creditor#create-a-creditor). ## What's next? #### [Adding a Creditor Bank Account](/docs/gc-embed/adding-a-creditor-bank-account) Add a bank account for each merchant so GoCardless can settle funds to the right place. #### [Setting a Scheme Identifier](/docs/gc-embed/setting-a-scheme-identifier) Request a custom scheme identifier so your merchant's name appears on payers' bank statements. ## Handling Webhooks URL: https://docs.gocardless.com/docs/gc-embed/handling-webhooks > Handle webhooks in your GoCardless Embed integration. # Handling Webhooks In this step of the GoCardless Embed guide you will use GoCardless' webhooks to respond to event actions and send payer notifications. Follow the [staying up to date with webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) guide to: - create a webhook endpoint through the GoCardless dashboard. - set up a webhook handler to listen to webhook events. The API reference docs contain the [full list of event actions](/docs/api-reference/events). ## Payer Notifications All direct debit schemes require certain notifications to be sent to payers, for example when a mandate is set up or a certain amount of time before a payment is taken. As a user of the GoCardless Embed product, we expect you will want to send your own payer notifications so that you can customise and brand them as you see fit. GoCardless will send a webhook for every notification you need to send. This will allow you stay within the scheme rules. You can read this more detailed [guide on handling payer notifications](/docs/tutorials/handling-customer-notifications). ## What's next? #### [Reconciling Payouts](/docs/gc-embed/reconciling-payouts) Use GoCardless webhooks and the Payout Items API to reconcile your payouts. #### [Automated Payout Reporting](/docs/gc-embed/reconciling-payouts/automated-payout-reporting) Opt in to automatic daily payout reports for all your creditors. ## Reconciling Payouts URL: https://docs.gocardless.com/docs/gc-embed/reconciling-payouts > Reconcile payouts in your GoCardless Embed integration. # Reconciling Payouts In this step of the GoCardless Embed guide you will use GoCardless' webhooks and API to reconcile your payouts. GoCardless will pay out payments to the payout bank account you added earlier in this guide. When this happens, a "payout" record will be created which represents the transfer of funds. We will generally send a single payout each day for each currency you collect in. However, we may split the funds into multiple payouts if there are a very large number of payments to pay out. When a payout is sent, you will receive a webhook with `resource_type` "payouts" and `action` "paid". In addition, for each payment that has been paid out, we will send webhooks with `resource_type` "payments" and `action` "paid_out". The `links[payout]` attribute of that webhook will include the ID of the payout the payment appears in. For more detailed reconciliation, the best way to understand what's inside a payout is to use the [Payout Items API](/docs/api-reference/payout-item#get-all-payout-items-in-a-single-payout). ## Using the Payout Items API The Payout Items API lets you see the individual transactions that made up the total amount of a payout. You can think of a payout in terms of credits and debits. When we collect payments and add the money collected to their GoCardless balance - that's a credit. But there can also be debits against that balance - for example deductions for chargebacks. When we make a payout, we bundle up all of the outstanding credits and debits into it and reset the creditor's balance to zero. > **Info:** > We'll only make a payout when a merchant's balance is positive. Imagine that a merchant's balance > is zero, and they make a refund of £5.00. Their balance is now **-£5.00**. They then collect > payment of £10.00. Their balance is **+£5.00**, so we'll send them a payout, which will bundle up > the refund and the successful payment into its Payout Items. For each item in a payout, we expose: - an `amount` (which will be positive for credit, or negative for a debit) and will be in the currency the payment was taken in. - a `type` (which explains the reason for the credit or debit) and `links` to any relevant resources (usually a payment, `links.payment`). The types of payout items in the GoCardless Embed product are: | **Type** | **Description** | **Credit or debit** | **Links** | | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -------------------------------- | | Payment paid out (`payment_paid_out`) | A payment was successfully collected from a payer and is being passed on to your payout account. | Credit | `links.payment` | | Payment failed (`payment_failed`) | A payment appeared to have been collected from a payer successfully, but then the bank told us that it had in fact failed, so it is being deducted | Debit | `links.payment` | | Payment charged back (`payment_charged_back`) | A payment was successfully collected from a payer, but then the payer contacted their bank to reverse the transaction, so it is being deducted | Debit | `links.payment` | | Payment refunded (`payment_refunded`) | A payment was successfully collected from a payer, and then partially or fully refunded at your request, so the refunded amount is being deducted | Debit | `links.payment`, `links.mandate` | | Payer refunded (`refund`) | A refund was sent to a payer, not related to any particular payment, so the refunded amount is being deducted. | Debit | `links.mandate` | | Refund funds returned (`refund_funds_returned`) | A refund made at your request, and previously deducted from a payout failed to reach the payer, so the refunded amount is being credited. | Credit | `links.payment`, `links.mandate` | To see how these can fit together in the real world, let's imagine a payout as an example: | **Description** | **Type** | **Amount** | | ------------------------------------------------------- | ---------------------- | ---------- | | Payment successfully collected from Nick | `payment_paid_out` | +€20.00 | | Refund issued for Andrew's payment, collected last week | `payment_refunded` | -€5.00 | | Bianca's payment from last week, which was charged back | `payment_charged_back` | -€10.00 | | **Total** | \*\*\*\* | **+€5.00** | With the Payout Items API, you can look inside a payout and see the transactions that make it up, allowing you to explain transactions on the payer's bank statement. When you receive a "payout paid" webhook (`resource_type` "payouts" and `action` "paid"), you can then query the Payout Items API: ```php require 'vendor/autoload.php'; function processPayoutEvent($event) { $client = new \GoCardlessPro\Client([ 'access_token' => $_ENV["GOCARDLESS_ACCESS_TOKEN"], 'environment' => \GoCardlessPro\Environment::SANDBOX ]); $payoutId = $event->links['payout']; $payout = $client->payouts()->get($payoutId); echo $payout->amount; $payoutItems = $client ->payoutItems() ->all(["params" => ["payout" => $payoutId]]); foreach ($payoutItems as $payoutItem) { echo $payoutItem->amount; echo $payoutItem->type; echo $payoutItem->links->payment; } } ``` ```python import os import gocardless_pro def process_payout_event(event): client = gocardless_pro.Client( access_token=os.environ['GOCARDLESS_ACCESS_TOKEN'], environment='sandbox' ) payout_id = event['links']['payout'] payout = client.payouts.get(payout_id) print(payout.amount) payout_items = client.payout_items.all(params={"payout": payout_id}).records for payout_item in payout_items: print(payout_item.amount) print(payout_item.type) print(payout_item.links.payment) ``` ```ruby require 'gocardless_pro' def process_payout_event(event) client = GoCardlessPro::Client.new( access_token: ENV['GOCARDLESS_ACCESS_TOKEN'], environment: :sandbox ) payout_id = event.links.payout payout = @client.payouts.find(payout_id) puts payout.amount payout_items = client.payout_items.all(params: { payout: payout_id }) payout_items.each do |payout_item| puts payout_item.amount puts payout_item.type puts payout_item.links.payment end end ``` ```java import com.gocardless.GoCardlessClient; import com.gocardless.resources.Event; import com.gocardless.resources.Payout; import com.gocardless.resources.PayoutItem; public class PayoutsWebhookHandler { public static void handlePayoutPaidEvent(Event event) { GoCardlessClient client = GoCardlessClient .newBuilder(System.getenv("GOCARDLESS_ACCESS_TOKEN")) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); String payoutId = event.getLinks().getPayout(); Payout payout = client.payouts().get(payoutId).execute(); for (PayoutItem payoutItem : client.payoutItems().all().withPayout(payoutId).execute()) { System.out.println(payoutItem.getAmount()); System.out.println(payoutItem.getType()); System.out.println(payoutItem.getLinks().getPayment()); } } } ``` ```javascript const gocardless = require("gocardless-nodejs"); const client = gocardless(process.env.GoCardlessAccessToken, constants.Environments.Sandbox); async function processPayoutEvent(event) { const payoutId = event.links.payout; const payout = await client.payouts.find(payoutId); console.log(payout.id); const payoutItems = client.payoutItems.all({ payout: payoutId }); for await (let payoutItem of payoutItems) { console.log(payoutItem.amount); console.log(payoutItem.type); console.log(payoutItem.links.payment); } } ``` ```net using GoCardless; public void HandlePayoutPaidEvent(GoCardless.Resources.Event event) { var client = GoCardlessClient.Create( ConfigurationManager.AppSettings["GoCardlessAccessToken"], GoCardlessClient.Environment.SANDBOX ); var payoutId = event.Links.Payout; var payoutResponse = await client.Payouts.GetAsync(payoutId); var payout = paymentResponse.Payout; Console.WriteLine(payout.Id); var payoutItemsRequest = new GoCardless.Services.PayoutItemListRequest() { Payout = payoutId }; var payoutItems = client.PayoutItems.All(payoutItemsRequest); foreach (GoCardless.Resources.PayoutItem payoutItem in payoutItems) { Console.WriteLine(payoutItem.Amount); Console.WriteLine(payoutItem.Type); Console.WriteLine(payoutItem.Links.Payment); } } ``` ```go package main import ( "context" "fmt" "http" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } parseEvent := func(event gocardless.Event) { payoutId := event.Links.Payout ctx := context.TODO() payoutListParams := gocardless.PayoutItemListParams{ Payout: payoutId, } payoutItems, err := client.PayoutItems().All(ctx, payoutListParams) for _, payoutItem := range payoutItems { fmt.Println(payoutItem.Amount) fmt.Println(payoutItem.Type) fmt.Println(payoutItem.Links.Payment) } } http.HandleFunc("/webhookEndpoint", func(w http.ResponseWriter, r *http.Request) { wh, err := gocardless.NewWebhookHandler("secret", gocardless.EventHandlerFunc(func(event gocardless.Event) error { parseEvent(event) })) wh.ServeHTTP(w, r) }) } ``` For full details on the Payout Items API, head over to our [reference documentation](/docs/api-reference/payout-item). ## What's next? Your integration is complete. Please [contact us](https://get.gocardless.com/l/1118633/2026-03-26/skf8xj) to help you take your integration live. #### [Automated Payout Reporting](/docs/gc-embed/reconciling-payouts/automated-payout-reporting) Opt in to automatic daily payout reports for all your creditors via the Exports API. #### [Setting Up Branding](/docs/gc-embed/setting-up-branding) Customise the look and feel of your merchants' payment pages with logos and colour themes. ## Setting a Scheme Identifier URL: https://docs.gocardless.com/docs/gc-embed/setting-a-scheme-identifier > Set a scheme identifier (optional). # Setting a Scheme Identifier > **Info:** > Setting a scheme identifier is optional. By default payments will use the account level scheme > identifier. In this step of the GoCardless Embed guide, you will create a scheme identifier for a given creditor. In order for your merchant's name to appear on their payers' bank statements, you will need to request custom scheme identifiers. Different schemes have different scheme identifiers (e.g. SUNs in Bacs and CIDs in SEPA). Therefore you must request a scheme identifier for each scheme you plan to collect payments in. ## Creating a scheme identifier You can create a scheme identifier by performing a POST request to the `/scheme_identifiers` endpoint. The required parameters are: | Parameter | Description | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | name | The name which will appear on the payer's bank statement. This will usually be the merchant's trading name. | | scheme | The scheme which this scheme identifier applies to. The supported schemes for the GoCardless Embed product are: `bacs` (UK direct debit), `faster_payments` (UK Pay By Banks), `sepa_core` (Eurozone direct debit), and `ach` (US direct debit). | | links[creditor] | The ID of the creditor to link the scheme identifier to. Creditors start with 'CR' | Examples of how to make this request using the GoCardless [client libraries](/docs/developer-resources/client-libraries): ```http POST https://api.gocardless.com/scheme_identifiers HTTP/1.1 Content-Type: application/json { "scheme_identifiers": { "name": "The Wine Club", "scheme": "bacs", "links": { "creditor": "CR123" } } } HTTP/1.1 201 Created Location: /scheme_identifiers/SU123 Content-Type: application/json { "scheme_identifiers": { "id": "SU123", "created_at": "2021-01-23T13:44:19.006Z", "name": "The Wine Club", "scheme": "bacs", "status": "pending", "currency": "GBP", ... }, } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/scheme_identifiers" \ -d @- << EOF { "scheme_identifiers": { "name": "The Wine Club", "scheme": "bacs", "links": { "creditor": "CR123" } } } EOF ``` ```php $client->schemeIdentifiers()->create([ 'params' => [ 'scheme' => 'bacs', 'name' => 'Example Ltd' 'links' => ['creditor' => 'CR123']] ] ]); ``` ```python client.scheme_identifiers.create(params={ "scheme": "bacs", "name": "Example Ltd", "links": { "creditor": "CR123" } }) ``` ```ruby @client.scheme_identifiers.create( params: { scheme: "bacs", name: "Example Ltd", links: { creditor: "CR123" } } ) ``` ```java SchemeIdentifier schemeIdentifier = client.schemeIdentifiers().create() .withScheme(SchemeIdentifierService.SchemeIdentifierCreateRequest.Scheme.BACS) .withName("The Wine Club") .withLinksCreditor("CR123") .execute(); ``` ```javascript const schemeIdentifier = await client.schemeIdentifiers.create({ scheme: "bacs", name: "The Wine Club", links: { creditor: "CR123", }, }); ``` ```net SchemeIdentifierCreateRequest schemeIdentifierRequest = new SchemeIdentifierCreateRequest { Name = "The Wine Club", Scheme = SchemeIdentifierCreateRequest.SchemeIdentifierScheme.Bacs, Links = new SchemeIdentifierCreateRequest.SchemeIdentifierLinks() { Creditor = "CR0123" } }; var schemeIdentifierResponse = await client.SchemeIdentifiers.CreateAsync(schemeIdentifierRequest); GoCardless.Resources.SchemeIdentifier schemeIdentifier = schemeIdentifierResponse.SchemeIdentifier; ``` ```go package main import ( gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } context := context.Background() schemeIdentifierCreateParams := gocardless.SchemeIdentifierCreateParams{ Name: "Durian Co", Scheme: "bacs", Links: gocardless.SchemeIdentifierCreateParamsLinks{ Creditor: "CR123", }, } schemeIdentifier, err := client.SchemeIdentifiers.Create(context, schemeIdentifierCreateParams) if err != nil { fmt.Printf("error creating scheme identifier: %s", err.Error()) return } ``` For more details, see the [API reference docs for creating scheme identifiers](/docs/api-reference/scheme-identifier#create-a-scheme-identifier). ## Scheme identifier status The scheme identifier status will be `pending` while GoCardless is processing the request. Once the scheme identifier is ready to be used the status will be updated to `active`. At this point, GoCardless will emit a [scheme identifier activated event](/docs/api-reference/events/scheme-identifier#activated) via webhook to notify you of this change. In Bacs, it will take up to five working days for a scheme identifier to become active. On other schemes, including SEPA, this happens instantly. ## What's next? #### [Setting Up Mandates & Payments](/docs/gc-embed/setting-up-mandates-collecting-payments) Use Billing Requests to set up Direct Debit mandates and collect payments from your customers. #### [API Reference: Scheme Identifiers](/docs/api-reference/scheme-identifier) Full reference documentation for the Scheme Identifiers API. ## Setting Up Branding URL: https://docs.gocardless.com/docs/gc-embed/setting-up-branding > Set up branding for your GoCardless Embed integration (optional). # Setting Up Branding > **Info:** > Setting up branding for each of your creditors is optional. If you do not add branding for a > creditor they will inherit any branding you have applied to your primary creditor. If you are using the GoCardless Hosted Payment Pages or the Javascript Drop-in, you can customise the look and feel of your merchants' payment pages and notification emails by adding a logo or setting the colour theme. ## How branding is applied to your merchants All your merchants (represented as creditors in GoCardless) start off without any custom branding. If you add branding to your primary creditor, the customisation settings will be inherited by all your creditors. This means if you want all your merchants to have the same branding, you only need to configure this once against your primary creditor. If you add branding to a specific creditor, this will override the primary creditor settings for that creditor. This means if merchant X wants to have their own branding, you can apply it to their creditor and their logo and colour themes will appear to that merchant's customers only. ## How to set up custom branding ### Dashboard To do this in the dashboard and preview what the page will look like: - Navigate to the creditor you want to update - Click `Update branding` in the top right corner - Upload a logo for the creditor - Customise the payment page's colours ### API To do this using the GoCardless API, you can use the following steps: #### POST /branding/logos You can upload a logo to a creditor by performing a POST request to the `/branding/logos` endpoint. If a creditor already has a logo, this will update the existing logo linked to the creditor. The required parameters are: | Parameter | Description | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | image | Base64 encoded string of the image to be uploaded. Must be in the format `"data:;base64,"`. Max file size is 0.5MB. | | links[creditor] | ID of the creditor the logo belongs to. | Examples of how to make this request using the GoCardless [client libraries](/docs/developer-resources/client-libraries): ```http POST https://api.gocardless.com/branding/logos HTTP/1.1 Content-Type: application/json { "logos": { "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", "links": { "creditor": "CR123" } } } HTTP/1.1 201 Created Content-Type: application/json { "logos": { "id": "LO123" } } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/branding/logos" \ -d @- << EOF { "logos": { "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", "links": { "creditor": "CR123" } } } EOF ``` ```php $client->logos()->createForCreditor([ "params" => [ "image" => "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", "links" => [ "creditor" => "CR123" ] ] ]); ``` ```python client.logos.create_for_creditor(params={ "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", "links": { "creditor": "CR123" } }) ``` ```ruby @client.logos.create_for_creditor( params: { image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", links: { creditor: "CR123" } } ) ``` ```java Logo logo = client.logos().createForCreditor() .withImage("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA") .withLinksCreditor("CR123") .execute(); ``` ```javascript const logo = await client.logos.createForCreditor({ image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", links: { creditor: "CR123", }, }); ``` ```net var logoCreateForCreditorRequest = new GoCardless.Services.LogoCreateForCreditorRequest() { Image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", Links = new GoCardless.Services.LogoCreateForCreditorRequest.LogoLinks() { Creditor = "CR0123" } }; var logoCreateForCreditorResponse = await gocardless.Logos.CreateForCreditorAsync(logoCreateForCreditorRequest); GoCardless.Resources.Logo creditorLogo = logoCreateForCreditorResponse.LogoResponse; ``` ```go package main import ( gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } logoCreateForCreditorParams := gocardless.LogoCreateForCreditorParams{ Image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA", Links: gocardless.LogoCreateForCreditorParamsLinks{ Creditor: "CR123", }, } logo, err := client.Logos.CreateForCreditor(context, logoCreateForCreditorParams) ``` For more details, see the API [reference docs for creating logos](/docs/api-reference/logo#create-a-logo-associated-with-a-creditor). #### POST /branding/payer_themes You can add payer colour themes to a creditor's branding by performing a POST request to the `/branding/payer_themes` endpoint. If a creditor already has payer themes, this will update the existing payer theme linked to the creditor. The required parameters are: | Parameters | Description | | ------------------------- | ---------------------------------------------- | | button_background_colour | The hexcode colour for button background | | content_box_border_colour | The hexcode colour for for content box borders | | header_background_colour | The hexcode colour for the header background | | link_text_colour | The hexcode colour for text links | | links[creditor] | ID of the creditor the payer theme belongs to. | Examples of how to make this request using the GoCardless [client libraries](/docs/developer-resources/client-libraries): ```http POST https://api.gocardless.com/branding/payer_themes HTTP/1.1 Content-Type: application/json { "payer_themes": { "header_background_colour": "#BD10E0", "link_text_colour": "#7ED321", "button_background_colour": "#128DAA", "content_box_border_colour": "#BD10E0", "links": { "creditor": "CR123" } } } HTTP/1.1 201 Created Content-Type: application/json { "payer_themes": { "id": "PTH123" } } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/branding/logos" \ -d @- << EOF { "payer_themes": { "header_background_colour": "#BD10E0", "link_text_colour": "#7ED321", "button_background_colour": "#128DAA", "content_box_border_colour": "#BD10E0", "links": { "creditor": "CR123" } } } EOF ``` ```php $client->payerThemes()->createForCreditor([ "params" => [ "header_background_colour" => "#BD10E0", "link_text_colour" => "#7ED321", "button_background_colour" => "#128DAA", "content_box_border_colour" => "#BD10E0", "links" => [ "creditor" => "CR123" ] ] ]); ``` ```python client.payer_themes.create_for_creditor(params={ "header_background_colour": "#BD10E0", "link_text_colour": "#7ED321", "button_background_colour": "#128DAA", "content_box_border_colour": "#BD10E0", "links": { "creditor": "CR123" } }) ``` ```ruby @client.payer_themes.create_for_creditor( params: { "header_background_colour": "#BD10E0", "link_text_colour": "#7ED321", "button_background_colour": "#128DAA", "content_box_border_colour": "#BD10E0", "links": { "creditor": "CR123" } } ) ``` ```java PayerTheme payerTheme = client.payerThemes().createForCreditor() .withButtonBackgroundColour("#128DAA") .withContentBoxBorderColour("#BD10E0") .withHeaderBackgroundColour("#BD10E0") .withLinkTextColour("#7ED321") .withLinksCreditor("CR123") .execute(); ``` ```javascript const payerThemes = await client.payerThemes.createForCreditor({ header_background_colour: "#BD10E0", link_text_colour: "#7ED321", button_background_colour: "#128DAA", content_box_border_colour: "#BD10E0", links: { creditor: "CR123", }, }); ``` ```net var payerThemeCreateForCreditorRequest = new GoCardless.Services.PayerThemeCreateForCreditorRequest() { HeaderBackgroundColour = "#BD10E0", LinkTextColour = "#7ED321", ButtonBackgroundColour = "#128DAA", ContentBoxBorderColour = "#BD10E0", Links = new GoCardless.Services.PayerThemeCreateForCreditorRequest.PayerThemeLinks() { Creditor = "CR0123" } }; var payerThemeCreateForCreditorResponse = await gocardless.PayerThemes.CreateForCreditorAsync(payerThemeCreateForCreditorRequest); GoCardless.Resources.PayerTheme creditorPayerTheme = payerThemeCreateForCreditorResponse.PayerThemeResponse; ``` ```go package main import ( gocardless "github.com/gocardless/gocardless-pro-go/v6" ) accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } payerThemeCreateForCreditorParams := gocardless.PayerThemeCreateForCreditorParams{ ButtonBackgroundColour: "#128DAA", ContentBoxBorderColour: "#BD10E0", HeaderBackgroundColour: "#BD10E0", LinkTextColour: "#7ED321", Links: gocardless.PayerThemeCreateForCreditorParamsLinks{ Creditor: "CR123", }, } payerThemes, err := client.PayerThemes.CreateForCreditor(context, payerThemeCreateForCreditorParams) ``` For more details, see the API [reference docs for creating payer themes](/docs/api-reference/payer-theme). ## Tips for uploading your logo Here are a few tips to help make your logo looks great across your customer payment page and notification emails. We support JPG and PNG formats. Your logo will be scaled to a maximum of 300px by 40px. #### Use a rectangular format Rectangular logos display best. Square logos will appear smaller and may be harder for your customers to read. #### Crop tightly Crop your logo tightly with minimal extra space to make it appear as large as possible. #### Use a solid background Save your logo on a solid background colour. Avoid photography or multiple colours within your logo. #### Ensure good contrast Make sure the background colour contrasts well with your logo so your customers can clearly see it. #### Keep it concise Avoid unnecessary words and taglines to keep your logo easy to read. #### Use transparent PNG Save your logo as a transparent PNG file. This way, you can easily change the background colour independently. ## What's next? #### [API Request Signing](/docs/gc-embed/api-request-signing) Add an extra layer of security by signing your API requests with ECDSA keys. #### [Bank Details Access](/docs/gc-embed/bank-details-access) Access encrypted bank account details for your customers. ## Setting up Mandates and Collecting Payments URL: https://docs.gocardless.com/docs/gc-embed/setting-up-mandates-collecting-payments > Set up mandates and collect payments with GoCardless Embed. # Setting up Mandates and Collecting Payments In the next step of the GoCardless Embed guide, you will use Billing Requests to set up mandates and take payments. The Billing Request API guides you through the necessary steps to create Direct Debit mandates and take payments from your customers. The things to keep in mind when following this GoCardless Embed guide are: - You must pass the creditor ID when creating a Billing Request in order to link it to the correct merchant. - You will build [custom payment pages](/docs/collect-payments/setting-up-mandates). This will allow you to use the white-labelled version of the GoCardless product so you can create a fully white-labelled merchant experience. - Custom payment pages must be compliant with scheme regulations. You can see the payment page regulations for each scheme [here](/docs/api-reference/compliance-requirements). ## What's next? #### [Setting Up a DD Mandate](/docs/gc-embed/setting-up-mandates-collecting-payments/actions-dd-mandate) Set up a Direct Debit mandate using Billing Request with Actions in a single API call. #### [Collecting a DD Payment](/docs/gc-embed/setting-up-mandates-collecting-payments/collecting-dd-payment) Collect a Direct Debit payment against a mandate you've already set up. #### [Pay By Bank](/docs/gc-embed/setting-up-mandates-collecting-payments/actions-instant-payment) Request a Pay By Bank using a Billing Request with Actions. #### [Dual Flow](/docs/gc-embed/setting-up-mandates-collecting-payments/actions-dual-flow) Collect a Pay By Bank and set up a Direct Debit mandate in a single flow. ## Automated Payout Reporting URL: https://docs.gocardless.com/docs/gc-embed/reconciling-payouts/automated-payout-reporting > Automate payout reporting in GoCardless Embed. # Automated Payout Reporting > **Info:** > To opt into Automated Payout Reporting, please contact your account manager to enable this > feature. **Automated Payout Reporting** means GoCardless will automatically generate a daily payout report for all your creditors, accessible to you in a single comprehensive report. GoCardless will generate a csv report for each currency you receive payouts in. The report will contain all the payouts you have received the previous business day (in UTC timezone), including any refunds, chargebacks or late failures incurred. More details on this format are in the [reconciling payouts](/docs/gc-embed/reconciling-payouts) section of our docs. If you require more historical information or reports that aggregate payouts across wider time frames you can generate manual payout reconciliation reports via the [dashboard](https://manage.gocardless.com/payouts) using the _payout reconciliation_ button and exporting the _transactions_. ## Getting your automated reports In this step of the GoCardless Embed guide, you will use GoCardless' APIs to retrieve the payout reports and download them to be consumed in your own reconciliation flows. ## Using the Exports API ### GET /exports You can retrieve the list of exports available for download by performing a GET request to the `/exports` endpoint. Exports are available for download for up to **3 days **after they are generated, after which they will no longer be available. ```http GET https://api.gocardless.com/exports HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json { "exports": [ { "id": "EX123", "created_at": "2014-01-01T12:00:00.000Z", "export_type": "payout_transactions_reconciliation", "currency": "GBP" }, { "id": "EX456", "created_at": "2014-01-01T12:00:00.000Z", "export_type": "payout_transactions_reconciliation", "currency": "EUR" } ] } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/exports" ``` ```php $client->exports()->list(); ``` ```python client.exports.list().records ``` ```ruby @client.exports.list ``` ```java for (Export export : client.exports().all().execute()) { System.out.println(export.getId()); } ``` ```javascript const exports = await client.exports.list(); ``` ```net var exportListResponse = gocardless.Exports.All(); foreach (GoCardless.Resources.Export export in exportListResponse) { Console.WriteLine(export.Id); } ``` ```go exportListParams := gocardless.ExportListParams{} exportListResult, err := client.Exports.List(context, exportListParams) for _, export := range exportListResult.Exports { fmt.Println(export.Id) } ``` ### GET /exports/EX123 To download an export, you can retrieve the download URL by performing a GET request to the `/exports/EX123` endpoint, providing the export ID as a path parameter. Once a download_url is generated, the link is accessible for up to **1 hour** before it expires. ```http GET https://api.gocardless.com/exports/EX123 HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json { "exports": { "id": "EX123", "created_at": "2014-01-01T12:00:00.000Z", "export_type": "payout_transactions_reconciliation", "download_url": "https://downloads.gocardless.com/EX123/example.csv", "currency": "GBP" } } ``` ```bash curl --silent \ -H "Content-Type: application/json" \ -H "Gocardless-Version: 2015-07-06" \ -H "Authorization: Bearer ${API_ACCESS_TOKEN}" \ "https://api.gocardless.com/exports/EX123" ``` ```php $client->exports()->get('EX123'); ``` ```python client.exports.get("EX123") ``` ```ruby @client.exports.get("EX123") ``` ```java Export export = client.exports().get("EX123").execute(); ``` ```javascript const exportData = await client.exports.find("EX123"); ``` ```net var exportResponse = await gocardless.Exports.GetAsync("EX123"); GoCardless.Resources.Export export = exportResponse.Export; ``` ```go export, err := client.Exports.Get(context, "EX123") ``` For more details, see the API reference docs for [Exports](/docs/api-reference/export#list-exports). ## What's next? #### [Setting Up Branding](/docs/gc-embed/setting-up-branding) Customise the look and feel of your merchants' payment pages with logos and colour themes. #### [API Request Signing](/docs/gc-embed/api-request-signing) Add an extra layer of security to your API communication with request signing. ## Collecting a Direct Debit Payment URL: https://docs.gocardless.com/docs/gc-embed/setting-up-mandates-collecting-payments/collecting-dd-payment > Collect a Direct Debit payment using GoCardless Embed. # Collecting a Direct Debit payment After calling the `Billing Request with Actions` we will now use the mandate ID (`MD123`) from the API response in order to create a Direct Debit payment. For this reason we'll now call the `Payments` API. ```http POST https://api.gocardless.com/payments HTTP/1.1 Content-Type: application/json { "payments": { "amount": 123, "currency": "GBP", "reference": "Wine Box", "charge_date": "2026-12-31", "links": { "mandate": "MD123" }, "metadata": { "internal_order_number": "ID123" }, } } HTTP/1.1 201 Created Location: /payments/PM123 Content-Type: application/json { "payments": { "id": "PM123", "scheme": "bacs" ... "charge_date": "2026-12-31", "amount": 123, ... "status": "pending_submission", ... "links": { "mandate": "MD123", "creditor": "CR123" }, ... } } ``` ```bash curl -X POST "https://api.gocardless.com/payments" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "GoCardless-Version: 2015-07-06" \ -H "Content-Type: application/json" \ -d '{ "payments": { "amount": 123, "currency": "GBP", "reference": "Wine Box", "charge_date": "2026-12-31", "links": { "mandate": "MD123" }, "metadata": { "internal_order_number": "ID123" } } }' ``` ```php $client->payments()->create([ "params" => [ "amount" => 123, "currency" => "GBP", "reference" => "Wine Box", "charge_date" => "2026-12-31", "metadata" => [ "internal_order_number" => "ID123" ], "links" => [ "mandate" => "MD123" ] ] ]); ``` ```python client.payments.create(params={ "amount": 123, "currency": "GBP", "reference": "Wine Box", "charge_date": "2026-12-31", "metadata": { "internal_order_number": "ID123" }, "links": { "mandate": "MD123" } }) ``` ```ruby @client.payments.create( params: { amount: 123, currency: "GBP", reference: "Wine Box", charge_date: "2026-12-31", metadata: { internal_order_number: "ID123" }, links: { mandate: "MD123" } } ) ``` ```java import com.gocardless.services.PaymentService.PaymentCreateRequest.Currency; Payment payment = client.payments().create() .withAmount(123) .withCurrency(Currency.GBP) .withReference("Wine Box") .withChargeDate("2026-12-31") .withMetadata("internal_order_number", "ID123") .withLinksMandate("MD123") .execute(); ``` ```javascript const payment = await client.payments.create({ amount: 123, currency: "GBP", reference: "Wine Box", charge_date: "2026-12-31", metadata: { internal_order_number: "ID123", }, links: { mandate: "MD123", }, }); ``` ```net var paymentRequest = new GoCardless.Services.PaymentCreateRequest() { Amount = 123, Currency = GoCardless.Services.PaymentCreateRequest.PaymentCurrency.GBP, Reference = "Wine Box", ChargeDate = "2026-12-31", Metadata = new Dictionary() { {"internal_order_number", "ID123"} }, Links = new GoCardless.Services.PaymentCreateRequest.PaymentLinks() { Mandate = "MD123" } }; var paymentResponse = await gocardless.Payments.CreateAsync(paymentRequest); GoCardless.Resources.Payment payment = paymentResponse.Payment; ``` ```go paymentCreateParams := gocardless.PaymentCreateParams{ Amount: 123, Currency: "GBP", Reference: "Wine Box", ChargeDate: "2026-12-31", Metadata: map[string]interface{}{"internal_order_number": "ID123"}, Links: gocardless.PaymentCreateParamsLinks{ Mandate: "MD123", }, } payment, err := client.Payments.Create(context, paymentCreateParams) ``` Note that the amount needs to be provided in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). You can decide to either provide a `charge_date` (needs to be later than the `next_possible_charge_date`, as described in the [mandates API reference](/docs/api-reference/mandate#list-mandates)), or let GoCardless create the payment as soon as possible. You would then be able to see the date that the payment will be taken by looking at the `charge_date` in the response. ## What's next? #### [Pay By Bank](/docs/gc-embed/setting-up-mandates-collecting-payments/actions-instant-payment) Request a Pay By Bank using a Billing Request with Actions. #### [Dual Flow](/docs/gc-embed/setting-up-mandates-collecting-payments/actions-dual-flow) Collect a Pay By Bank and set up a DD mandate in a single flow. ## Dual Flow URL: https://docs.gocardless.com/docs/gc-embed/setting-up-mandates-collecting-payments/actions-dual-flow > Use Billing Request actions for dual flow in GC Embed. # Dual Flow Similarly to the previous three guides above, we will also be able to use the `Billing Request with Actions` in order to request a Pay By Bank and create a Direct Debit mandate. We'll be able to create both requests at the same time within one flow. By combining both a `payment_request` as well as a `mandate_request` in the API request, we'll be able to omit having to pass the customer's bank account details, as those would be retrieved automatically from the Pay By Bank. In order to complete all the actions on the `mandate_request` we'll need to pass all required `customer_billing_details` including the payer's billing address. > **Warning:** > The customer's `email` is a mandatory field for Payment Providers using our Embed product. ```http POST https://api.gocardless.com/billing_requests/create_with_actions HTTP/1.1 Content-Type: application/json { "billing_request_with_actions": { "payment_request": { "description": "Pay By Bank", "amount": 123, "currency": "GBP", "metadata": { "internal_payment_id": "ID123" } }, "mandate_request": { "currency": "GBP", "scheme": "bacs", "verify": "recommended", "metadata": { "mandate_metadata": "ID456" } }, "actions": { "collect_customer_details": { "customer": { "given_name": "Alice", "family_name": "Smith", "email": "alice.smith@example.com", ... }, "customer_billing_detail": { "address_line1": "Street 123", "city": "London", ... } }, "select_institution": { "institution": "INSTITUTION_ID123", "country_code": "GB" }, "bank_authorisation_redirect_uri": "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation": true }, "links": { "creditor": "CR123" } } } HTTP/1.1 201 Created Content-Type: application/json { "billing_request_with_actions": { "billing_requests": { "id": "BRQ123", "created_at": "2025-12-16T14:58:06.643Z", "status": "pending", "mandate_request": { ... "currency": "GBP", ... }, "payment_request": { "description": "Penny payment", "currency": "GBP", "amount": 123, "scheme": "faster_payments", ... }, ... "links": { "customer": "CU123", ... "creditor": "CR123", ... }, ... "bank_authorisations": { "id": "BA123", "url": "https://institution.com/...", "qr_code_url": "https://pay-sandbox.gocardless.com/obauth/BA123/qr_code", "created_at": "2025-12-04T13:47:16.645Z", ... "expires_at": "2025-12-04T14:02:16.632Z", ... "links": { ... "institution": "INSTITUTION_ID123" } } } } } ``` ```bash curl -X POST "https://api.gocardless.com/billing_requests/create_with_actions" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "GoCardless-Version: 2015-07-06" \ -H "Content-Type: application/json" \ -d '{ "billing_request_with_actions": { "payment_request": { "description": "Pay By Bank", "amount": 123, "currency": "GBP", "metadata": { "internal_payment_id": "ID123" } }, "mandate_request": { "currency": "GBP", "scheme": "bacs", "verify": "recommended", "metadata": { "mandate_metadata": "ID456" } }, "actions": { "collect_customer_details": { "customer": { "given_name": "Alice", "family_name": "Smith", "email": "alice.smith@example.com" }, "customer_billing_detail": { "address_line1": "Street 123", "city": "London" } }, "select_institution": { "institution": "INSTITUTION_ID123", "country_code": "GB" }, "bank_authorisation_redirect_uri": "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation": true }, "links": { "creditor": "CR123" } } }' ``` ```php $client->billingRequestsWithActions()->create([ "params" => [ "payment_request" => [ "description" => "Pay By Bank", "amount" => 123, "currency" => "GBP", "metadata" => [ "internal_payment_id" => "ID123" ] ], "mandate_request" => [ "currency" => "GBP", "scheme" => "bacs", "verify" => "recommended", "metadata" => [ "mandate_metadata" => "ID456" ] ], "actions" => [ "collect_customer_details" => [ "customer" => [ "given_name" => "Alice", "family_name" => "Smith", "email" => "alice.smith@example.com" ], "customer_billing_detail" => [ "address_line1" => "Street 123", "city" => "London" ] ], "select_institution" => [ "institution" => "INSTITUTION_ID123", "country_code" => "GB" ], "bank_authorisation_redirect_uri" => "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation" => true ], "links" => [ "creditor" => "CR123" ] ] ]); ``` ```python client.billing_requests_with_actions.create(params={ "payment_request": { "description": "Pay By Bank", "amount": 123, "currency": "GBP", "metadata": { "internal_payment_id": "ID123" } }, "mandate_request": { "currency": "GBP", "scheme": "bacs", "verify": "recommended", "metadata": { "mandate_metadata": "ID456" } }, "actions": { "collect_customer_details": { "customer": { "given_name": "Alice", "family_name": "Smith", "email": "alice.smith@example.com" }, "customer_billing_detail": { "address_line1": "Street 123", "city": "London" } }, "select_institution": { "institution": "INSTITUTION_ID123", "country_code": "GB" }, "bank_authorisation_redirect_uri": "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation": True }, "links": { "creditor": "CR123" } }) ``` ```ruby @client.billing_requests_with_actions.create( params: { payment_request: { description: "Pay By Bank", amount: 123, currency: "GBP", metadata: { internal_payment_id: "ID123" } }, mandate_request: { currency: "GBP", scheme: "bacs", verify: "recommended", metadata: { mandate_metadata: "ID456" } }, actions: { collect_customer_details: { customer: { given_name: "Alice", family_name: "Smith", email: "alice.smith@example.com" }, customer_billing_detail: { address_line1: "Street 123", city: "London" } }, select_institution: { institution: "INSTITUTION_ID123", country_code: "GB" }, bank_authorisation_redirect_uri: "https://pay.gocardless.com/billing/static/thankyou", create_bank_authorisation: true }, links: { creditor: "CR123" } } ) ``` ```java BillingRequestWithActions response = client.billingRequestsWithActions().create() .withPaymentRequestDescription("Pay By Bank") .withPaymentRequestAmount(123) .withPaymentRequestCurrency("GBP") .withPaymentRequestMetadata("internal_payment_id", "ID123") .withMandateRequestCurrency("GBP") .withMandateRequestScheme("bacs") .withMandateRequestVerify("recommended") .withMandateRequestMetadata("mandate_metadata", "ID456") .withActionsCollectCustomerDetailsCustomerGivenName("Alice") .withActionsCollectCustomerDetailsCustomerFamilyName("Smith") .withActionsCollectCustomerDetailsCustomerEmail("alice.smith@example.com") .withActionsCollectCustomerDetailsCustomerBillingDetailAddressLine1("Street 123") .withActionsCollectCustomerDetailsCustomerBillingDetailCity("London") .withActionsSelectInstitutionInstitution("INSTITUTION_ID123") .withActionsSelectInstitutionCountryCode("GB") .withActionsBankAuthorisationRedirectUri("https://pay.gocardless.com/billing/static/thankyou") .withActionsCreateBankAuthorisation(true) .withLinksCreditor("CR123") .execute(); ``` ```javascript const response = await client.billingRequestsWithActions.create({ payment_request: { description: "Pay By Bank", amount: 123, currency: "GBP", metadata: { internal_payment_id: "ID123", }, }, mandate_request: { currency: "GBP", scheme: "bacs", verify: "recommended", metadata: { mandate_metadata: "ID456", }, }, actions: { collect_customer_details: { customer: { given_name: "Alice", family_name: "Smith", email: "alice.smith@example.com", }, customer_billing_detail: { address_line1: "Street 123", city: "London", }, }, select_institution: { institution: "INSTITUTION_ID123", country_code: "GB", }, bank_authorisation_redirect_uri: "https://pay.gocardless.com/billing/static/thankyou", create_bank_authorisation: true, }, links: { creditor: "CR123", }, }); ``` ```net var paymentRequest = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsPaymentRequest { Description = "Pay By Bank", Amount = 123, Currency = "GBP", Metadata = new Dictionary() { {"internal_payment_id", "ID123"} } }; var mandateRequest = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsMandateRequest { Currency = "GBP", Scheme = "bacs", Verify = GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsMandateRequestVerify.Recommended, Metadata = new Dictionary() { {"mandate_metadata", "ID456"} } }; var collectCustomerDetails = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetails { Customer = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetailsCustomer { GivenName = "Alice", FamilyName = "Smith", Email = "alice.smith@example.com" }, CustomerBillingDetail = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetailsCustomerBillingDetail { AddressLine1 = "Street 123", City = "London" } }; var selectInstitution = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsSelectInstitution { Institution = "INSTITUTION_ID123", CountryCode = "GB" }; var resp = await gocardless.BillingRequestsWithActions.CreateAsync( new GoCardless.Services.BillingRequestWithActionsCreateRequest { PaymentRequest = paymentRequest, MandateRequest = mandateRequest, Actions = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActions { CollectCustomerDetails = collectCustomerDetails, SelectInstitution = selectInstitution, BankAuthorisationRedirectUri = "https://pay.gocardless.com/billing/static/thankyou", CreateBankAuthorisation = true }, Links = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsLinks { Creditor = "CR123" } } ); ``` ```go billingRequestWithActionsCreateParams := gocardless.BillingRequestWithActionsCreateParams{ PaymentRequest: &gocardless.BillingRequestWithActionsCreateParamsPaymentRequest{ Description: "Pay By Bank", Amount: 123, Currency: "GBP", Metadata: map[string]interface{}{"internal_payment_id": "ID123"}, }, MandateRequest: &gocardless.BillingRequestWithActionsCreateParamsMandateRequest{ Currency: "GBP", Scheme: "bacs", Verify: "recommended", Metadata: map[string]interface{}{"mandate_metadata": "ID456"}, }, Actions: &gocardless.BillingRequestWithActionsCreateParamsActions{ CollectCustomerDetails: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetails{ Customer: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetailsCustomer{ GivenName: "Alice", FamilyName: "Smith", Email: "alice.smith@example.com", }, CustomerBillingDetail: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetailsCustomerBillingDetail{ AddressLine1: "Street 123", City: "London", }, }, SelectInstitution: &gocardless.BillingRequestWithActionsCreateParamsActionsSelectInstitution{ Institution: "INSTITUTION_ID123", CountryCode: "GB", }, BankAuthorisationRedirectUri: "https://pay.gocardless.com/billing/static/thankyou", CreateBankAuthorisation: true, }, Links: &gocardless.BillingRequestWithActionsCreateParamsLinks{ Creditor: "CR123", }, } response, err := client.BillingRequestsWithActions.Create(context, billingRequestWithActionsCreateParams) ``` We can see that the Billing Request is still in a `pending` status. This means that the Direct Debit mandate has not yet been created. Only if the customer approved the Pay By Bank request by authorising the bank authorisation either via their mobile banking app or via desktop, we'll then see that the mandate was created. The customer will be able to approve this request by being redirected to the `url` parameter. - In a mobile-to-mobile flow we'd ideally use a call-to-action so that the customer is immediately redirected to this link after they clicked on a button. - In a desktop-to-mobile flow, we could use the `qr_code_url` instead. This will allow the customer to scan the qr code on your website using their mobile device in order to then authorise the Pay By Bank request via their banking app. Listening to the `bank_authorisation_authorised` [webhook](/docs/api-reference/bank-authorisation#get-a-bank-authorisation) allows us to make sure that the customer has approved the payment request. Listening to the `payment_confirmed` [webhook](/docs/api-reference/events/payment#confirmed) notifies us that the payment has been successfully collected. Once the customer had approved the bank authorisation, the status of the Billing Request would then move from `pending` to `fulfilled`. The Direct Debit mandate will be created. ## What's next? #### [Handling Webhooks](/docs/gc-embed/handling-webhooks) Listen to webhooks to track authorisation, payment confirmation, and mandate creation. #### [Reconciling Payouts](/docs/gc-embed/reconciling-payouts) Use the Payout Items API to reconcile your merchants' payouts. ## Pay By Bank URL: https://docs.gocardless.com/docs/gc-embed/setting-up-mandates-collecting-payments/actions-instant-payment > Use Billing Request actions to take a Pay By Bank in GC Embed. # Pay By Bank In order to request a Pay By Bank, we'll need to initiate a `payment_request`. In this instance, we are going to set the currency to GBP and will need to link the `Billing Request with Actions` to the creditor we wish to pay out to, `CR123`. The required actions of the Billing Request will be different from those of a `mandate_request`. In order to generate the payment request url for the customer, we will also need to provide the `institution` as well as a `bank_authorisation_redirect_uri`. Setting the `create_bank_authorisation` to `true` allows us to retrieve the redirect `url` in the API response. The list of available institution IDs can be obtained from the [Institutions API](/docs/api-reference/institution#list-institutions-for-billing-request). > **Warning:** > The customer's `email` is a mandatory field for Payment Providers using our Embed product. ```http POST https://api.gocardless.com/billing_requests/create_with_actions HTTP/1.1 Content-Type: application/json { "billing_request_with_actions": { "payment_request": { "description": "Pay By Bank", "amount": 123, "currency": "GBP", "metadata": { "internal_payment_id": "ID123" } }, "actions": { "collect_customer_details": { "customer": { "given_name": "Alice", "family_name": "Smith", "email": "alice.smith@example.com", ... } }, "select_institution": { "institution": "INSTITUTION_ID123", "country_code": "GB" }, "bank_authorisation_redirect_uri": "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation": true }, "links": { "creditor": "CR123" } HTTP/1.1 200 OK Content-Type: application/json { "billing_request_with_actions": { "billing_requests": { "id": "BRQ123", "created_at": "2025-12-04T13:47:16.211Z", "status": "pending", ... "payment_request": { "description": "Sleek Granite Tuna", "currency": "GBP", "amount": 1230, ... }, ... "links": { "customer": "CU123", ... "creditor": "CR123", "... }, ... "bank_authorisations": { "id": "BA123", "url": "https://institution.com/...", "qr_code_url": "https://pay-sandbox.gocardless.com/obauth/BA123/qr_code", "created_at": "2025-12-04T13:47:16.645Z", ... "expires_at": "2025-12-04T14:02:16.632Z", ... "links": { ... "institution": "INSTITUTION_ID123" } } } } ``` ```bash curl -X POST "https://api.gocardless.com/billing_requests/create_with_actions" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "GoCardless-Version: 2015-07-06" \ -H "Content-Type: application/json" \ -d '{ "billing_request_with_actions": { "payment_request": { "description": "Pay By Bank", "amount": 123, "currency": "GBP", "metadata": { "internal_payment_id": "ID123" } }, "actions": { "collect_customer_details": { "customer": { "given_name": "Alice", "family_name": "Smith", "email": "alice.smith@example.com" } }, "select_institution": { "institution": "INSTITUTION_ID123", "country_code": "GB" }, "bank_authorisation_redirect_uri": "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation": true }, "links": { "creditor": "CR123" } } }' ``` ```php $client->billingRequestsWithActions()->create([ "params" => [ "payment_request" => [ "description" => "Pay By Bank", "amount" => 123, "currency" => "GBP", "metadata" => [ "internal_payment_id" => "ID123" ] ], "actions" => [ "collect_customer_details" => [ "customer" => [ "given_name" => "Alice", "family_name" => "Smith", "email" => "alice.smith@example.com" ] ], "select_institution" => [ "institution" => "INSTITUTION_ID123", "country_code" => "GB" ], "bank_authorisation_redirect_uri" => "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation" => true ], "links" => [ "creditor" => "CR123" ] ] ]); ``` ```python client.billing_requests_with_actions.create(params={ "payment_request": { "description": "Pay By Bank", "amount": 123, "currency": "GBP", "metadata": { "internal_payment_id": "ID123" } }, "actions": { "collect_customer_details": { "customer": { "given_name": "Alice", "family_name": "Smith", "email": "alice.smith@example.com" } }, "select_institution": { "institution": "INSTITUTION_ID123", "country_code": "GB" }, "bank_authorisation_redirect_uri": "https://pay.gocardless.com/billing/static/thankyou", "create_bank_authorisation": True }, "links": { "creditor": "CR123" } }) ``` ```ruby @client.billing_requests_with_actions.create( params: { payment_request: { description: "Pay By Bank", amount: 123, currency: "GBP", metadata: { internal_payment_id: "ID123" } }, actions: { collect_customer_details: { customer: { given_name: "Alice", family_name: "Smith", email: "alice.smith@example.com" } }, select_institution: { institution: "INSTITUTION_ID123", country_code: "GB" }, bank_authorisation_redirect_uri: "https://pay.gocardless.com/billing/static/thankyou", create_bank_authorisation: true }, links: { creditor: "CR123" } } ) ``` ```java BillingRequestWithActions response = client.billingRequestsWithActions().create() .withPaymentRequestDescription("Pay By Bank") .withPaymentRequestAmount(123) .withPaymentRequestCurrency("GBP") .withPaymentRequestMetadata("internal_payment_id", "ID123") .withActionsCollectCustomerDetailsCustomerGivenName("Alice") .withActionsCollectCustomerDetailsCustomerFamilyName("Smith") .withActionsCollectCustomerDetailsCustomerEmail("alice.smith@example.com") .withActionsSelectInstitutionInstitution("INSTITUTION_ID123") .withActionsSelectInstitutionCountryCode("GB") .withActionsBankAuthorisationRedirectUri("https://pay.gocardless.com/billing/static/thankyou") .withActionsCreateBankAuthorisation(true) .withLinksCreditor("CR123") .execute(); ``` ```javascript const response = await client.billingRequestsWithActions.create({ payment_request: { description: "Pay By Bank", amount: 123, currency: "GBP", metadata: { internal_payment_id: "ID123", }, }, actions: { collect_customer_details: { customer: { given_name: "Alice", family_name: "Smith", email: "alice.smith@example.com", }, }, select_institution: { institution: "INSTITUTION_ID123", country_code: "GB", }, bank_authorisation_redirect_uri: "https://pay.gocardless.com/billing/static/thankyou", create_bank_authorisation: true, }, links: { creditor: "CR123", }, }); ``` ```net var paymentRequest = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsPaymentRequest { Description = "Pay By Bank", Amount = 123, Currency = "GBP", Metadata = new Dictionary() { {"internal_payment_id", "ID123"} } }; var collectCustomerDetails = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetails { Customer = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetailsCustomer { GivenName = "Alice", FamilyName = "Smith", Email = "alice.smith@example.com" } }; var selectInstitution = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsSelectInstitution { Institution = "INSTITUTION_ID123", CountryCode = "GB" }; var resp = await gocardless.BillingRequestsWithActions.CreateAsync( new GoCardless.Services.BillingRequestWithActionsCreateRequest { PaymentRequest = paymentRequest, Actions = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActions { CollectCustomerDetails = collectCustomerDetails, SelectInstitution = selectInstitution, BankAuthorisationRedirectUri = "https://pay.gocardless.com/billing/static/thankyou", CreateBankAuthorisation = true }, Links = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsLinks { Creditor = "CR123" } } ); ``` ```go billingRequestWithActionsCreateParams := gocardless.BillingRequestWithActionsCreateParams{ PaymentRequest: &gocardless.BillingRequestWithActionsCreateParamsPaymentRequest{ Description: "Pay By Bank", Amount: 123, Currency: "GBP", Metadata: map[string]interface{}{"internal_payment_id": "ID123"}, }, Actions: &gocardless.BillingRequestWithActionsCreateParamsActions{ CollectCustomerDetails: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetails{ Customer: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetailsCustomer{ GivenName: "Alice", FamilyName: "Smith", Email: "alice.smith@example.com", }, }, SelectInstitution: &gocardless.BillingRequestWithActionsCreateParamsActionsSelectInstitution{ Institution: "INSTITUTION_ID123", CountryCode: "GB", }, BankAuthorisationRedirectUri: "https://pay.gocardless.com/billing/static/thankyou", CreateBankAuthorisation: true, }, Links: &gocardless.BillingRequestWithActionsCreateParamsLinks{ Creditor: "CR123", }, } response, err := client.BillingRequestsWithActions.Create(context, billingRequestWithActionsCreateParams) ``` We will now be able to grab the `url` parameter and send it to our customer. - In a mobile-to-mobile flow we'd ideally use a call-to-action so that the customer is immediately redirected to this link after they clicked on a button. - In a desktop-to-mobile flow, we could use the `qr_code_url` instead. This will allow the customer to scan the qr code on your website using their mobile device in order to then authorise the Pay By Bank request via their banking app. Listening to the `bank_authorisation_authorised` [webhook](/docs/api-reference/events/billing-request) allows us to make sure that the customer has approved the payment request. Listening to the `payment_confirmed` [webhook](/docs/api-reference/events/payment) notifies us that the payment has been successfully collected. Once the customer has approved the payment request and the funds were collected from their bank account, the status of the Billing Request will then move from `pending` to `fulfilled`. ## What's next? #### [Dual Flow](/docs/gc-embed/setting-up-mandates-collecting-payments/actions-dual-flow) Combine a Pay By Bank and a Direct Debit mandate setup in a single flow. #### [Handling Webhooks](/docs/gc-embed/handling-webhooks) Listen to webhooks to confirm payment authorisation and fulfilment. ## Setting Up a DD Mandate URL: https://docs.gocardless.com/docs/gc-embed/setting-up-mandates-collecting-payments/actions-dd-mandate > Use Billing Request actions to set up a Direct Debit mandate in GC Embed. # Setting Up a DD Mandate ## What is the aim of this tutorial? This tutorial aims to familiarise Embed PSP integrators with the `Billing Request with Actions / Billing Request` and will explain setting up either a Pay By Bank, or a Direct Debit mandate and subsequent Direct Debit payment or a Pay By Bank as well as Direct Debit mandate in a dual flow. ## Getting started For this tutorial, you will need: - An [API token](/docs/getting-started/set-up#step-by-step-guide) - The GoCardless client library of your choice configured in your language of choice - A [Creditor](/docs/api-reference/creditor) to collect payments against ## Billing Request with Actions: Setting up a Direct Debit mandate We can start by creating a `Billing Request with Actions`. This will allow us to set up a mandate, which is linked to a creditor. In order to create a mandate, we'll initiate a `mandate_request` and specify the `scheme` (for Pay By Bank it would be a `payment_request`). In this instance, we are going to use `bacs` for a GBP mandate. You will need to pass the full payer's billing address to create a `bacs` Direct Debit mandate. If you want to collect in EUR, use `sepa_core`. We link the `Billing Request with Actions` to the creditor we wish to pay out to, `CR123`. With this endpoint you'll be able to complete all required `actions` to fulfil the mandate request in one single API call. The required `actions` of the `Billing Request` can change depending on the type of payment being taken or set up (e.g a Direct Debit mandate or a Pay By Bank). We don't need to worry about them too much in this tutorial - but it's good to be aware of them! You can read more about them in [billing request actions](/docs/collect-payments/setting-up-mandates) if you're interested. > **Warning:** > The customer's email is a mandatory field for Payment Providers using our Embed product. ```http POST https://api.gocardless.com/billing_requests/create_with_actions HTTP/1.1 Content-Type: application/json { "billing_request_with_actions": { "mandate_request": { "scheme": "bacs", ... }, "actions": { "collect_customer_details": { "customer": { "given_name": "Alice", "family_name": "Smith", "email": "alice.smith@example.com", ... }, "customer_billing_detail": { "address_line1": "1 Somewhere Lane", ... } }, "collect_bank_account": { "country_code": "GB", "account_holder_name": "Alice Smith", "account_number": "55779911", "branch_code": "200000" } }, "links": { "creditor": "CR123" } } } HTTP/1.1 200 OK Content-Type: application/json { "billing_request_with_actions": { "billing_requests": { "id": "BRQ123", "created_at": "2025-12-04T10:59:05.144Z", "status": "fulfilled", "mandate_request": { "currency": "GBP", "scheme": "bacs", "links": { "mandate": "MD123" }, ... } ``` ```bash curl -X POST "https://api.gocardless.com/billing_requests/create_with_actions" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "GoCardless-Version: 2015-07-06" \ -H "Content-Type: application/json" \ -d '{ "billing_request_with_actions": { "mandate_request": { "currency": "GBP", "scheme": "bacs" }, "actions": { "collect_customer_details": { "customer": { "email": "alice@example.com", "given_name": "Alice", "family_name": "Smith" }, "customer_billing_detail": { "address_line1": "1 Example Street", "city": "London", "postal_code": "W1 1AA", "country_code": "GB" } }, "collect_bank_account": { "account_number": "55779911", "branch_code": "200000", "account_holder_name": "Alice Smith", "country_code": "GB" }, "confirm_payer_details": {} } } }' ``` ```php $client->billingRequestsWithActions()->create([ "params" => [ "mandate_request" => [ "currency" => "GBP", "scheme" => "bacs" ], "actions" => [ "collect_customer_details" => [ "customer" => [ "email" => "alice@example.com", "given_name" => "Alice", "family_name" => "Smith" ], "customer_billing_detail" => [ "address_line1" => "1 Example Street", "city" => "London", "postal_code" => "W1 1AA", "country_code" => "GB" ] ], "collect_bank_account" => [ "account_number" => "55779911", "branch_code" => "200000", "account_holder_name" => "Alice Smith", "country_code" => "GB" ], "confirm_payer_details" => [] ] ] ]); ``` ```python client.billing_requests_with_actions.create(params={ "mandate_request": { "currency": "GBP", "scheme": "bacs" }, "actions": { "collect_customer_details": { "customer": { "email": "alice@example.com", "given_name": "Alice", "family_name": "Smith" }, "customer_billing_detail": { "address_line1": "1 Example Street", "city": "London", "postal_code": "W1 1AA", "country_code": "GB" } }, "collect_bank_account": { "account_number": "55779911", "branch_code": "200000", "account_holder_name": "Alice Smith", "country_code": "GB" }, "confirm_payer_details": {} } }) ``` ```ruby @client.billing_requests_with_actions.create( params: { mandate_request: { currency: "GBP", scheme: "bacs" }, actions: { collect_customer_details: { customer: { email: "alice@example.com", given_name: "Alice", family_name: "Smith" }, customer_billing_detail: { address_line1: "1 Example Street", city: "London", postal_code: "W1 1AA", country_code: "GB" } }, collect_bank_account: { account_number: "55779911", branch_code: "200000", account_holder_name: "Alice Smith", country_code: "GB" }, confirm_payer_details: {} } } ) ``` ```java BillingRequestWithActions response = client.billingRequestsWithActions().create() .withMandateRequestCurrency("GBP") .withMandateRequestScheme("bacs") .withActionsCollectCustomerDetailsCustomerEmail("alice@example.com") .withActionsCollectCustomerDetailsCustomerGivenName("Alice") .withActionsCollectCustomerDetailsCustomerFamilyName("Smith") .withActionsCollectCustomerDetailsCustomerBillingDetailAddressLine1("1 Example Street") .withActionsCollectCustomerDetailsCustomerBillingDetailCity("London") .withActionsCollectCustomerDetailsCustomerBillingDetailPostalCode("W1 1AA") .withActionsCollectCustomerDetailsCustomerBillingDetailCountryCode("GB") .withActionsCollectBankAccountAccountNumber("55779911") .withActionsCollectBankAccountBranchCode("200000") .withActionsCollectBankAccountAccountHolderName("Alice Smith") .withActionsCollectBankAccountCountryCode("GB") .withActionsConfirmPayerDetails(true) .execute(); ``` ```javascript const response = await client.billingRequestsWithActions.create({ mandate_request: { currency: "GBP", scheme: "bacs", }, actions: { collect_customer_details: { customer: { email: "alice@example.com", given_name: "Alice", family_name: "Smith", }, customer_billing_detail: { address_line1: "1 Example Street", city: "London", postal_code: "W1 1AA", country_code: "GB", }, }, collect_bank_account: { account_number: "55779911", branch_code: "200000", account_holder_name: "Alice Smith", country_code: "GB", }, confirm_payer_details: {}, }, }); ``` ```net var mandateRequest = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsMandateRequest { Currency = "GBP", Scheme = "bacs" }; var collectCustomerDetails = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetails { Customer = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetailsCustomer { Email = "alice@example.com", GivenName = "Alice", FamilyName = "Smith" }, CustomerBillingDetail = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectCustomerDetailsCustomerBillingDetail { AddressLine1 = "1 Example Street", City = "London", PostalCode = "W1 1AA", CountryCode = "GB" } }; var collectBankAccount = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsCollectBankAccount { AccountNumber = "55779911", BranchCode = "200000", AccountHolderName = "Alice Smith", CountryCode = "GB" }; var resp = await gocardless.BillingRequestsWithActions.CreateAsync( new GoCardless.Services.BillingRequestWithActionsCreateRequest { MandateRequest = mandateRequest, Actions = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActions { CollectCustomerDetails = collectCustomerDetails, CollectBankAccount = collectBankAccount, ConfirmPayerDetails = new GoCardless.Services.BillingRequestWithActionsCreateRequest.BillingRequestWithActionsActionsConfirmPayerDetails() } } ); ``` ```go billingRequestWithActionsCreateParams := gocardless.BillingRequestWithActionsCreateParams{ MandateRequest: &gocardless.BillingRequestWithActionsCreateParamsMandateRequest{ Currency: "GBP", Scheme: "bacs", }, Actions: &gocardless.BillingRequestWithActionsCreateParamsActions{ CollectCustomerDetails: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetails{ Customer: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetailsCustomer{ Email: "alice@example.com", GivenName: "Alice", FamilyName: "Smith", }, CustomerBillingDetail: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectCustomerDetailsCustomerBillingDetail{ AddressLine1: "1 Example Street", City: "London", PostalCode: "W1 1AA", CountryCode: "GB", }, }, CollectBankAccount: &gocardless.BillingRequestWithActionsCreateParamsActionsCollectBankAccount{ AccountNumber: "55779911", BranchCode: "200000", AccountHolderName: "Alice Smith", CountryCode: "GB", }, ConfirmPayerDetails: &gocardless.BillingRequestWithActionsCreateParamsActionsConfirmPayerDetails{}, }, } response, err := client.BillingRequestsWithActions.Create(context, billingRequestWithActionsCreateParams) ``` For the purpose of this tutorial, we will only need to keep track of the mandate ID (`MD123`) from the API response in order to create a Direct Debit payment. ## What's next? #### [Collecting a DD Payment](/docs/gc-embed/setting-up-mandates-collecting-payments/collecting-dd-payment) Use the mandate ID from the previous step to collect a Direct Debit payment. #### [Pay By Bank](/docs/gc-embed/setting-up-mandates-collecting-payments/actions-instant-payment) Request a Pay By Bank using a Billing Request with Actions. --- # Partners ## Introduction URL: https://docs.gocardless.com/docs/partner-integrations > Overview of GoCardless partner integrations — accept bank payments directly within your software. # For Partner Integrators ## Introduction As a partner, you can accept bank payments on your software. GoCardless establishes a direct relationship with your users, and processes payments on your behalf. In this guide, we'll cover all of the key steps required for building an integration. > **Tip:** > Click **"What's Next"** at the bottom of each page to follow the integration flow and see code > examples. ## Before you start: [Sign up for a sandbox account](https://manage-sandbox.gocardless.com/sign-up) and test your integration without moving real money ### 1. Create a partner account - [Create an app](https://manage-sandbox.gocardless.com/partners/apps/create) on the GoCardless dashboard - [Use OAuth](/docs/partner-integrations/connect-your-merchants) and get authorisation to make API calls on your user's behalf - [Help your users get verified](/docs/partner-integrations/getting-your-users-verified) ### 2. Accept and manage payments (build your integration) - [Use the billing request API and flow](/docs/partner-integrations/setting-up-mandates) to collect payments - [Set up webhooks to listen for payment events](/docs/partner-integrations/webhooks-for-partners) - [Use payment intelligence products](/docs/optimise/reduced-failed-payments-with-success-plus) to optimise merchant's revenue - [Reconcile your payouts](/docs/collect-payments/managing-payments/reconciling-payouts) - [Follow UX best practices](/docs/partner-integrations/ux-guides-and-resources) on how to build and display GoCardless in your application ### 3. Go live - Set your [production environment](https://manage.gocardless.com/) and add your app - Complete your compliance checks - [Complete the self-assessment review](/docs/partner-integrations/go-live-checklist) You can monitor your connected merchants, payment volume, and webhook health from the [Partner Dashboard](https://manage.gocardless.com/). Just click "Switch to Partner View" in the side nav. ## Guides #### [Connect your merchants](/docs/partner-integrations/connect-your-merchants) Use OAuth to securely connect your users' GoCardless accounts and obtain access tokens. #### [Integration guide](/docs/partner-integrations/integration-guide) Work through the best-practices checklist before going live. ## Connect Your Merchants URL: https://docs.gocardless.com/docs/partner-integrations/connect-your-merchants > Connect to your users # Connecting your users account ## Connecting your users' accounts In this first step of the partner integration guide, we'll take you through securely gaining access to your users' GoCardless accounts. You'll end up with an access token, which we'll be able to use later on in this guide to set up mandates and payments on your user's behalf. ## OAuth: an introduction You must connect your users' accounts via our OAuth 2 flow To set up mandates and payments for your users, you'll need access to their GoCardless account so you can make API requests on their behalf. Our OAuth flow allows you to securely obtain an access token for a GoCardless account without having to have your user's password or do any manual setup. There are four key benefits to getting access to your users' accounts using OAuth: #### It Your users have a secure way to grant you access to their account without needing to send you their login credentials or an access token. They only need to tell us that you may have access through a simple online process. #### It You only need to generate and send your user a link to our OAuth flow. From there, they'll create a GoCardless account or sign in to their existing one, approve your access to their account, and then we'll send them right back to you with an access token. #### It Linking to your users' accounts using OAuth makes you eligible to earn a commission for each payment they process through your product, either by adding your own fees on top of GoCardless's or by receiving a share of GoCardless's fees. #### It As the GoCardless API gets better and better over time and offers new functionality, you'll be able to stay up-to-date and use all the latest features. ## Using the OAuth flow ### 01. Creating an App Before we can get started, you need to create an "app" in the sandbox environment which represents your partner's integration in the GoCardless system. You'll be issued with a client ID and secret, which you'll use to identify yourself when sending users to the OAuth flow and swapping `code`s for access tokens. First, [sign up for a GoCardless account](https://manage-sandbox.gocardless.com/sign-up) in our sandbox testing environment and then [create an app](https://manage-sandbox.gocardless.com/partners/apps/create). You'll need to provide a name, a description and the URL of your homepage (where users can go to read more about your product or your integration with GoCardless). We won't specify the post-onboarding URL or webhook URL for now. Once your user has completed the OAuth flow, they will be redirected to your application using the `redirect_url` parameter you provide. For security reasons, this can't be just any internet URL, so you will need to configure at least one redirect URL here (which must exactly match the parameter). You may wish to add additional redirect URLs, for example when also testing against your local application, but we'll only allow up to 20 redirect URLs in total. ![Using the OAuth flow - Creating an app copy](/images/docs/partner-integrations/connect-your-merchants/using_the_oauth_flow_-_creating_an_app_copy.png) Once you've created an app, you'll see it in the [list of your apps in your Dashboard](https://manage-sandbox.gocardless.com/partners/apps). Click on your newly-created app, and take a note of the Client ID and Client Secret. ### 02. Generating a link to the OAuth flow Let's get started by installing an OAuth client library: ```php composer require adoy/oauth2 ``` ```python pip install oauth2client ``` ```ruby echo "gem 'oauth2'" >> Gemfile bundle install ``` ```java <-- Add the following to your Maven file --> com.squareup.okhttp3 okhttp 3.4.1 ``` Now we've installed the library, we can build a link to the OAuth flow. We'll have to pass in a number of parameters, including the `client_id` and `client_secret`, as well as a few parameters that will vary by library. These can include: | Parameter | Description | | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **The URL of the GoCardless OAuth flow** | In the sandbox, this is **https://connect-sandbox.gocardless.com/oauth/authorize**. It'll form the base of the URL your client library generates. | | **A redirect URL** | The URL to send your users to once they've agreed to connect their account to GoCardless (as well if they deny authorisation or something goes wrong, in which case we'll pass you details of the error). This must exactly match one of the redirect URLs you specified above. | | **The URL of the GoCardless access token API** | The URL of the API endpoint will be used to exchange the code for an access token after your user has been redirected back to your redirect URL. In the sandbox environment, this is **https://connect-sandbox.gocardless.com/oauth/access_token**. | | **scope** | The level of access you want to your users' GoCardless accounts - this may either be `read_write` or `read_only`. | | **response_type** | The kind of OAuth request you're making - only `code` is supported. | | **initial_view (optional)** | An optional parameter, set to either `signup` or `login` to specify which view we should show when your user enters the OAuth flow. By default, they will see the login view if you're requesting `read_only` access and the signup view if requesting `read_write`. | | **state (optional)** | Any value you pass in here will be included as a query string parameter when we redirect back to your redirect URL. Please note that this value can be tampered with by your user, and so shouldn't be trusted implicitly. We recommend using this parameter for a [CSRF Token](https://en.wikipedia.org/wiki/Cross-site_request_forgery). | | **prefill[email] (optional)** | Your user's email address. We will prefill this on the login or signup forms to make it quicker and easier for them to complete the flow. | | **prefill[phone_number] (optional)** | Your user's phone number. We will pref-fill this on the signup forms. Number should be in this [E.164](https://en.wikipedia.org/wiki/E.164) format i.e. it should include the country code and the rest of the number e.g. +447599288282 | | **prefill[given_name] (optional)** | Your user's given (first) name. We will prefill this on the signup form. | | **prefill[family_name] (optional)** | Your user's family (last) name. We will prefill this on the signup form. | | **prefill[organisation_name] (optional)** | The name of the user's organisation (e.g. Acme Widget plc, 2nd Upminster Scout Group or Tim Rogers). We will prefill this on the signup form. | | **prefill[creditor_type] (optional)** | The organisation's business type. This should be one of: `charity`, `company`, `individual`, `partnership`, or `trust` | | **prefill[country_code] (optional)** | The country code of the users' organisation in [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code format. We will prefill this on the signup form. | | **language (optional)** | The language that the login/signup form should be in, is [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. If the language specified is supported, we will use it. Otherwise, we will fall back to the most appropriate available language for the user, based on factors like their browser settings and location. | ```php getAuthenticationUrl( // Once you go live, this should be set to https://connect.gocardless.com. You'll also // need to create a live app and update your client ID and secret. 'https://connect-sandbox.gocardless.com/oauth/authorize', 'https://acme.enterprises/redirect', // Your redirect URL [ 'scope' => 'read_write', 'initial_view' => 'login', 'prefill' => [ 'email' => 'tim@gocardless.com', 'given_name' => 'Tim', 'family_name' => 'Rogers', 'organisation_name' => 'Tim\'s Fishing Store', ], ] ); // You'll now want to direct your user to the URL - you could redirect them or display it // as a link on the page header("Location: " . $authorizeUrl); ``` ```python import os from oauth2client.client import OAuth2WebServerFlow # You should store your client ID and secret in environment variables rather than # committing them with your code flow = OAuth2WebServerFlow( client_id=os.environ['GOCARDLESS_CLIENT_ID'], client_secret=os.environ['GOCARDLESS_CLIENT_SECRET'], scope="read_write", redirect_uri="https://acme.enterprises/redirect", # Once you go live, this should be set to https://connect.gocardless.com. You'll also need to create a live app and update your client ID and secret. auth_uri="https://connect-sandbox.gocardless.com/oauth/authorize", token_uri="https://connect-sandbox.gocardless.com/oauth/access_token", initial_view="signup", prefill={ "email": "tim@gocardless.com", "given_name": "Tim", "family_name": "Rogers", "organisation_name": "Tim's Fishing Store" } ) authorize_url = flow.step1_get_authorize_url() # You'll now want to direct your user to the URL - you could redirect them or display it # as a link on the page flask.redirect(authorize_url, code=302) ``` ```ruby require 'oauth2' # You should store your client ID and secret in environment variables rather than # committing them with your code oauth = OAuth2::Client.new( ENV['GOCARDLESS_CLIENT_ID'], ENV['GOCARDLESS_CLIENT_SECRET'], # Once you go live, this should be set to # https://connect.gocardless.com. You'll also need to create # a live app and update your client ID and secret. site: 'https://connect-sandbox.gocardless.com', authorize_url: '/oauth/authorize', token_url: '/oauth/access_token', auth_scheme: :request_body ) authorize_url = oauth.auth_code.authorize_url( redirect_uri: 'https://acme.enterprises/redirect', scope: 'read_only', initial_view: 'signup', prefill: { email: "tim@gocardless.com", given_name: "Tim", family_name: "Rogers", organisation_name: "Tim's Fishing Store" } ) redirect_to authorize_url ``` ```java // See https://raw.githubusercontent.com/gocardless/gocardless-pro-java-maven-example/master/src/main/java/hello/OAuthController.java import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.http.HttpStatus; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.web.util.UriComponentsBuilder; @RestController public class OAuthController { private static final String authoriseRedirectUrl = "https://connect-sandbox.gocardless.com/oauth/authorize"; private static final String redirectUrl = "https://bb314345.ngrok.io/redirect"; private static final String clientID = System.getenv("GOCARDLESS_CLIENT_ID"); private static final String clientSecret = System.getenv("GOCARDLESS_CLIENT_SECRET"); @GetMapping("/") public ResponseEntity index() { String oauthUrl = UriComponentsBuilder .fromUriString(authoriseRedirectUrl) .queryParam("client_id", clientID) .queryParam("redirect_uri", redirectUrl) .queryParam("scope", "read_write") .queryParam("response_type", "code") .queryParam("initial_view", "signup") .queryParam("prefill[email]", "tim@gocardless.com") .queryParam("prefill[given_name]", "Tim") .queryParam("prefill[family_name]", "Rogers") .queryParam("prefill[organisation_name]", "Tim's Fishing Store") .queryParam("prefill[country_code]", "GB") .toUriString(); HttpHeaders headers = new HttpHeaders(); headers.add("Location", oauthUrl); return new ResponseEntity(oauthUrl, headers, HttpStatus.FOUND); } } ``` ```net // This is example code and must be inserted into your application structure private readonly string authoriseRedirectUrl = "https://connect-sandbox.gocardless.com/oauth/authorize"; private readonly string redirectUrl = "https://acme.enterprises/redirect"; private readonly string clientID = Environment.GetEnvironmentVariable("GOCARDLESS_CLIENT_ID"); private readonly string clientSecret = Environment.GetEnvironmentVariable("GOCARDLESS_CLIENT_SECRET"); public static void redirect() { var uriBuilder = new UriBuilder(authoriseRedirectUrl); uriBuilder.Query = "?client_id=" + clientID; uriBuilder.Query += "&redirect_uri=" + redirectUrl; uriBuilder.Query += "&scope=read_write"; uriBuilder.Query += "&response_type=code"; uriBuilder.Query += "&prefill[email]=tim@gocardless.com"; uriBuilder.Query += "&prefill[given_name]=Tim"; uriBuilder.Query += "&prefill[family_name]=Rogers"; uriBuilder.Query += "&prefill[organisation_name]=Fishing%20Store"; uriBuilder.Query += "&prefill[country_code]=GB"; Response.Redirect(uriBuilder.ToString()); } ``` With these parameters set correctly, the resulting URL will have the following format: ```bash https://connect-sandbox.gocardless.com/oauth/authorize?client_id=myid&initial_view=signup&prefill%5Bemail%5D=tim%40gocardless.com&redirect_uri=https%3A%2F%2Facme.enterprises%2Fredirect&response_type=code&scope=read_only ``` Run this code to generate a link to the OAuth flow. Head over to the link you've just generated in an Incognito window, and you'll see our OAuth flow. ![Create-an-account-Connect-your-GoCardless-Account](/images/docs/partner-integrations/connect-your-merchants/create-an-account-connect-your-gocardless-account.png) ### 03. Getting an access token > **Tip: Testing** > On the signup form, we recommend creating a second sandbox account using a different email > address. This will replicate what your users will experience when connecting to your partner > integration, and will give you an example account that you can use from the perspective of one of > your users. Once your user has either signed up or logged in and then approved your app's access to their account, they'll be sent to your app's redirect URI with a temporary `code` which you'll see in the query parameters, as well as any `state` you provided. You should use the OAuth client library we set up earlier to fetch an access token using the `code`. This is a permanent access token that allows you to use the API on behalf of your merchant at any time. ```php getAccessToken( 'https://connect-sandbox.gocardless.com/oauth/access_token', 'authorization_code', ['code' => $_GET['code'], 'redirect_uri' => 'https://acme.enterprises/redirect'] ); $payload = [ 'gocardless_access_token' => $response['result']['access_token'], 'gocardless_organisation_id' => $response['result']['organisation_id'], ]; $currentUser->update($payload); ``` ```python import os from requests_oauthlib import OAuth2Session from oauthlib.oauth2 import WebApplicationClient # Configuration client_id = os.environ['GOCARDLESS_CLIENT_ID'] client_secret = os.environ['GOCARDLESS_CLIENT_SECRET'] redirect_uri = "https://acme.enterprises/redirect" # Authorization endpoint and token endpoint for GoCardless (sandbox in this case) auth_base_url = "https://connect-sandbox.gocardless.com/oauth/authorize" token_url = "https://connect-sandbox.gocardless.com/oauth/access_token" scope = ["read_write"] # Create OAuth2 client oauth_client = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope) # Step 1: Redirect user to GoCardless for authorization authorization_url, state = oauth_client.authorization_url(auth_base_url) print(f"Visit this URL to authorize the app: {authorization_url}") # After the user authorizes the app, they will be redirected to your redirect_uri with a code parameter. # You will retrieve the code parameter in your web app after redirection. # For example, assuming you're in a web framework like Flask: # code = request.args.get('code') # Step 2: Exchange the authorization code for an access token # Replace 'code' with the authorization code obtained from the redirect code = 'authorization_code_from_redirect' token = oauth_client.fetch_token( token_url=token_url, code=code, client_id=client_id, client_secret=client_secret, include_client_id=True # Ensure the client_id is included in the request body ) # Step 3: Store the access token and organization ID access_token = token.get('access_token') organisation_id = token.get('organisation_id') # Now, you can store these tokens for later use: current_user.update( gocardless_access_token=access_token, gocardless_organisation_id=organisation_id ) ``` ```ruby require 'oauth2' # You should store your client ID and secret in environment variables rather than # committing them with your code oauth = OAuth2::Client.new( ENV['GOCARDLESS_CLIENT_ID'], ENV['GOCARDLESS_CLIENT_SECRET'], # Once you go live, this should be set to # https://connect.gocardless.com. You'll also need to create # a live app and update your client ID and secret. site: 'https://connect-sandbox.gocardless.com', authorize_url: '/oauth/authorize', token_url: '/oauth/access_token', auth_scheme: :request_body ) access_token = oauth.auth_code.get_token( params[:code], # You'll need to use exactly the same access token as you did in the last step redirect_uri: 'https://acme.enterprises/redirect' ) # You should store the user's access token - you'll need it to make API requests on their # behalf in future. If you want to handle webhooks for your users, you should also store # their organisation ID which will allow you to identify webhooks belonging to them. current_user.update!( gocardless_access_token: access_token.token, gocardless_organisation_id: access_token['organisation_id'] ) ``` ```java // See https://raw.githubusercontent.com/gocardless/gocardless-pro-java-maven-example/master/src/main/java/hello/OAuthController.java import okhttp3.FormBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; @RestController public class OAuthController { private static final String accessTokenUrl = "https://connect-sandbox.gocardless.com/oauth/access_token"; private static final String redirectUri = "https://bb314345.ngrok.io/redirect"; private static final String clientID = System.getenv("GOCARDLESS_CLIENT_ID"); private static final String clientSecret = System.getenv("GOCARDLESS_CLIENT_SECRET"); private static final OkHttpClient client = new OkHttpClient(); private String getAccessToken(String oauthCode) throws IOException { RequestBody body = new FormBody.Builder() .add("client_id", clientID) .add("client_secret", clientSecret) .add("redirect_uri", redirectUri) .add("grant_type", "authorization_code") .add("code", oauthCode) .build(); Request request = new Request.Builder() .url(accessTokenUrl) .post(body) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } } @GetMapping("/redirect") public String loggedIn(@RequestParam("code") String oauthCode) throws IOException { String accessToken = getAccessToken(oauthCode); System.out.println("Save the access token " + accessToken + " to your database."); return "Greetings!"; } } ``` ```net // This is example code and must be inserted into your application structure private readonly string accessTokenUrl = "https://connect-sandbox.gocardless.com/oauth/access_token"; private readonly string redirectUrl = "https://acme.enterprises/redirect"; private readonly string clientID = Environment.GetEnvironmentVariable("GOCARDLESS_CLIENT_ID"); private readonly string clientSecret = Environment.GetEnvironmentVariable("GOCARDLESS_CLIENT_SECRET"); public Task RedirectHandler(request Request) { var oauthCode = request.Query["code"].ToString(); using (HttpClient client = new HttpClient()) { using (MultipartFormDataContent data = new MultipartFormDataContent()) { data.Add(new StringContent(clientID), "client_id"); data.Add(new StringContent(clientSecret), "client_secret"); data.Add(new StringContent(redirectUrl), "redirect_uri"); data.Add(new StringContent("authorization_code"), "grant_type"); data.Add(new StringContent(redirectUrl), "redirect_uri"); data.Add(new StringContent(oauthCode), "code"); var response = await client.PostAsync(accessTokenUrl, data); var accessToken = response.Content return accessToken; } } } ``` Whether you are developing a mobile, web, or desktop application, it is important not to pass the client secret to your user's device as it could be used to impersonate your app. The process of exchanging a `code` for an access token should be done on your server so your client secret can be kept private. You'll want to store this access token in your database for use in the future to make requests to the GoCardless API on your user's behalf. **Make sure you keep it safe and secure, as it gives full access to your user's account.** > **Info: Revoking access** > Once your user has connected to your app, they can revoke your access from the GoCardless > dashboard, or you can [revoke (i.e. invalidate) their access token yourself using the > API](/docs/api-reference/oauth-reference). **We'd also strongly advise storing your user's GoCardless organisation ID**. Later on, we'll set up webhooks to keep your integration up to date as things happen to your users' mandates and payments. You'll need to use the organisation ID included in these webhooks to work out which of your users a particular event relates to. > **Tip:** > If you didn't store the user's GoCardless organisation ID and want it later, you can find it out > by [looking up the access token](/docs/api-reference/oauth-reference) using the API. If the redirect URL isn't the page where you ultimately want your user to arrive, you can redirect them from here to the right place, either before or after exchanging the code for an access token. Once you've stored your merchant's access token, we'd suggest presenting your customers with any relevant configuration options for the integration (e.g. setting how failed payments should be handled). We'd also recommend providing in-product tips or links to support materials and letting customers know that they'll need to [verify their account](/docs/partner-integrations/getting-your-users-verified) in order to receive payouts (they'll also receive emails from us reminding them to do this). > **Tip: Adding to your onboarding experience** > To get the best out of your integration, we'd suggest adding it to your onboarding experience and > prompting merchants to set up with GoCardless at key points in their product journey (e.g. setting > up an invoice, creating a customer, signing a contract etc.). From this process, you'd then send > them into the OAuth flow. [Take a look at some of our recommendations for bringing your > integration to your users' attention here](/docs/partner-integrations/ux-guides-and-resources). ### 04. Handling Disconnections As a partner, you may be disconnected from a merchant for two reasons: 1. The merchant can revoke your access 2. The merchant's GoCardless account can be closed. If you need to clean up any data on your side, we will send you a special, final [webhook](/docs/getting-started/stay-up-to-date-with-webhooks) when this happens. Since the shared access token will have been revoked, you will be unable to make any further API calls to GoCardless, so we suggest you reach out to the user directly if you think this has happened in error. This webhook is designed to look similar to other webhooks, i.e. it is wrapped in the `events` key. However, there is no associated event, so the event `id` is `null`. It also means you cannot immediately run a GET for the organisation details (as recommended for other webhook types), as the shared access token has been revoked. You can identify this event as it has resource_type `organisations` and action `disconnected`. As an example, we'll write a handler for this 'special' webhook: ```http POST https://example.com/webhooks HTTP/1.1 Content-Type: application/json { "events": [ { "id": null, "created_at": "2018-08-03T12:00:00.000Z", "action": "disconnected", "resource_type": "organisations", "links": { "organisation": "OR123" }, "details": { "cause": "app_disconnected", "origin": "gocardless", "description": "Your app has been has disconnected from this organisation" }, "metadata": {} } ] } ``` ```php action) { case "disconnected": print("Organisation " . $event->links->organisation . " has been disconnected!\n"); MarkOrganisationAsDisconnected($event->links->organisation); break; default: print("Don't know how to process an organisation " . $event->action . " event\n"); break; } } $webhook_endpoint_secret = getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET"); $request_body = file_get_contents('php://input'); $headers = getallheaders(); $signature_header = $headers["Webhook-Signature"]; try { $events = \GoCardlessPro\Webhook::parse( $request_body, $signature_header, $webhook_endpoint_secret ); foreach ($events as $event) { print("Processing event " . $event->id . "\n"); switch ($event->resource_type) { case "organisations": process_organisation_event($event); break; default: print("Don't know how to process an event with resource_type " . $event->resource_type . "\n"); break; } } header("HTTP/1.1 200 OK"); } catch (\GoCardlessPro\Core\Exception\InvalidSignatureException $e) { header("HTTP/1.1 498 Invalid Token"); } ``` ```python # Here, we're using a Django view, but essentially the same code will work in # other Python web frameworks (e.g. Flask) with minimal changes import os import logging from django.views.generic import View from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator from django.http import HttpResponse from gocardless_pro import webhooks, Client from gocardless_pro.errors import InvalidSignatureError from myinvoicingapp.models import GoCardlessEvent # Handle the incoming Webhook and perform an action with the Webhook data. class Webhook(View): logger = logging.getLogger(**name**) @method_decorator(csrf_exempt) def dispatch(self, *args, **kwargs): return super(Webhook, self).dispatch(*args, **kwargs) def post(self, request, *args, **kwargs): try: for event in self._get_events(request): self.process(event) return HttpResponse(204) except InvalidSignatureError: return HttpResponse(498) def process(self, event): self.logger.info("Processing event {}\n".format(event.id)) if event.resource_type == 'organisations': return self.process_organisation_event(event) # ... Handle other resource types else: self.logger.info("Don't know how to process an event with \ resource_type {}\n".format(event.resource_type)) def process_organisation_event(self, event): if event.action == 'disconnected': self.logger.info( "Organisation {} has been disconnected\n". format(event.links.organisation) ) else: self.logger.info("Don't know how to process an event with \ resource_type {}\n".format(event.resource_type)) def _get_events(self, request): secret = os.environ['GC_WEBHOOK_SECRET'] signature = request.META["HTTP_WEBHOOK_SIGNATURE"] body = request.body.strip() return webhooks.parse(body, secret, signature) ``` ```ruby require 'gocardless_pro' class OrganisationEventProcessor def self.process(event, response) case event.action when 'disconnected' response.stream.write("Organisation #{event.links.organisation} has been disconnected\n") DisconnectOrganisation.enqueue(event['links']['organisation']) else response.stream.write( "Don't know how to process a organisation #{event.action} event\n" ) end end end def create # We recommend storing your webhook endpoint secret in an environment variable # for security webhook_endpoint_secret = ENV['GOCARDLESS_WEBHOOK_ENDPOINT_SECRET'] # In a Rack app (e.g. Sinatra), access the POST body with # `request.body.tap(&:rewind).read` request_body = request.raw_post # In a Rack app (e.g. Sinatra), the header is available as # `request.env['HTTP_WEBHOOK_SIGNATURE']` signature_header = request.headers['Webhook-Signature'] begin events = GoCardlessPro::Webhook.parse( request_body: request_body, signature_header: signature_header, webhook_endpoint_secret: webhook_endpoint_secret ) events.each do |event| # We're using Rails's streaming functionality here to write directly to the # response rather than using views, as one would usually. response.stream.write("Processing event #{event.id}\n") case event.resource_type when 'organisations' OrganisationEventProcessor.process(event, response) else response.stream.write( "Don't know how to process an event with resource_type #{event.resource_type}\n" ) end end response.stream.close render status: 200 rescue GoCardlessPro::Webhook::InvalidSignatureError render status: 498 end end ``` ```java package hello; // Use the POM file at // https://raw.githubusercontent.com/gocardless/gocardless-pro-java-maven-example/master/pom.xml import com.gocardless.errors.InvalidSignatureException; import com.gocardless.resources.Event; import com.gocardless.Webhook; import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.http.ResponseEntity; @RestController public class HelloController { private String processDisconnections(Event event) { switch (event.getAction()) { case "disconnected": // here, you probably want to mark the organisation as disconnected // and stop sending any requests on their behalf return "Organisation " + event.getLinks().getOrganisation() + " has been cancelled.\n"; default: return "Do not know how to process an event with action " + event.getAction() + ".\n"; } } private String processEvent(Event event) { switch (event.getResourceType()) { case ORGANISATIONS: return processDisconnections(event); default: return "Don't know how to process an event of resource_type " + event.getResourceType().toString() + ".\n"; } } @PostMapping("/") public ResponseEntity handlePost( @RequestHeader("Webhook-Signature") String signatureHeader, @RequestBody String requestBody) { String webhookEndpointSecret = System.getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET"); try { List events = Webhook.parse(requestBody, signatureHeader, webhookEndpointSecret); String responseBody = ""; for (Event event : events) { responseBody += processEvent(event); } return new ResponseEntity(responseBody, HttpStatus.OK); } catch (InvalidSignatureException e) { return new ResponseEntity("Incorrect Signature", HttpStatus.BAD_REQUEST); } } } ``` > **Info: Monitor and manage your integration in the Partner Dashboard** > Once merchants are connected via OAuth, the [Partner Dashboard](https://manage.gocardless.com/) > gives you a live view of their connection status, verification, and activity. Click "Switch to > Partner View" in the side nav to access it. ## What's Next? #### [Get your users verified](/docs/partner-integrations/getting-your-users-verified) Check verification status and send users to the GoCardless onboarding flow before they can receive payouts. #### [Webhooks for partners](/docs/partner-integrations/webhooks-for-partners) Handle the disconnection webhook and other real-time events for your partner integration. ## Getting Your Users Verified URL: https://docs.gocardless.com/docs/partner-integrations/getting-your-users-verified > Get your users verified and onboarded onto GoCardless. # Onboarding your users ## Helping your users get verified Before your users can actually start collecting payments and getting their payouts, their GoCardless account needs to be verified. This is a must-do for anti-money laundering (AML) rules. The verification process is pretty straightforward, but it asks your users to: - Provide detailed information about their business. - Upload proof of identity and address. - Add their bank account details and prove ownership of the account. We collect all these details through our own dedicated, hosted onboarding flow. Once a user signs up to GoCardless via your app, you should immediately check their verification status and send them to this flow if they need to complete it. ## Checking a user's verification status Once a user completes the OAuth flow and you have an access token, you need to find out if the user needs to go through the verification process. Most new users will, but some might be connecting an existing, verified account. You can find your user's verification status in the **Creditors API** using the `verification_status` attribute. You can query it like this: ```php $currentUser->gocardlessAccessToken, 'environment' => \GoCardlessPro\Environment::SANDBOX ]); // The Creditors API returns a list of creditors, but any GoCardless account connected // to your application will have a single creditor, so you can just look at the first one $creditor = $client->creditors()->list()->records[0]; // We'll see below how to redirect users to the onboarding flow, and how it works if ($creditor->verification_status == "action_required") { redirectToOnboardingFlow(); } ``` ```python import gocardless_pro client = gocardless_pro.Client( access_token=current_user.gocardless_access_token, environment='sandbox' ) # The Creditors API returns a list of creditors, but any GoCardless account connected # to your application will have a single creditor, so you can just look at the first one creditor = client.creditors.list().records[0]; # We'll see below how to redirect users to the onboarding flow, and how it works if creditor.verification_status == "action_required": redirect_to_onboarding_flow() ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( access_token: current_user.gocardless_access_token, environment: :sandbox ) # The Creditors API returns a list of creditors, but any GoCardless account connected # to your application will have a single creditor, so you can just look at the first one creditor = client.creditors.list.records.first # We'll see below how to redirect users to the onboarding flow, and how it works redirect_to_onboarding_flow if creditor.verification_status == "action_required" ``` ```java package com.gcintegration; import com.gocardless.GoCardlessClient; import com.gocardless.resources.Creditor; import static com.gocardless.resources.Creditor.VerificationStatus.ACTION_REQUIRED; GoCardlessClient client = GoCardlessClient .newBuilder(CurrentUser.gocardlessAccessToken) .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); // The Creditors API returns a list of creditors, but any GoCardless account connected // to your application will have a single creditor, so you can just look at the first one Creditor creditor = client.creditors().list().execute().getItems().get(0); // We'll see below how to redirect users to the onboarding flow, and how it works if (creditor.getVerificationStatus() == ACTION_REQUIRED) { redirectToOnboardingFlow(); } ``` ```javascript const client = gocardless( // We recommend storing your access token in an environment // variable for security process.env.GoCardlessAccessToken, // Change me to constants.Environments.Live when you're ready to go live constants.Environments.Sandbox, ); const creditors = gocardless.creditors.list({ limit: 1 }); // The Creditors API returns a list of creditors, but any GoCardless account connected // to your application will have a single creditor, so you can just look at the first one const creditor = creditors.creditors[0]; if (creditor.verification_status === "action_required") { // We'll see below how to redirect users to the onboarding flow, and how it works redirectUserToOnboardingFlow(); } ``` ```net GoCardlessClient client = GoCardlessClient.Create( // We recommend storing your access token in an // configuration setting for security ConfigurationManager.AppSettings["GoCardlessAccessToken"], // Change me to LIVE when you're ready to go live GoCardlessClient.Environment.SANDBOX ); var creditorListResponse = await gocardless.Creditors.ListAsync( new GoCardless.Services.CreditorListRequest() { Limit = 1 } ); // The Creditors API returns a list of creditors, but any GoCardless account connected // to your application will have a single creditor, so you can just look at the first one GoCardless.Resources.Creditor creditor = creditorListResponse.Creditors[0]; if (creditor.VerificationStatus == CreditorVerificationStatus.ActionRequired) { // We'll see below how to redirect users to the onboarding flow, and how it works RedirectUserToOnboardingFlow(); } ``` ```go package main import ( "context" "fmt" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { accessToken := "your_access_token_here" opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint) client, err := gocardless.New(accessToken, opts) if err != nil { fmt.Println("error in initialisating client: %s", err.Err()) return } creditorListParams := gocardless.CreditorListParams{} creditorListParams.Limit = 1 ctx := context.TODO() creditors, err := client.Creditors.List(ctx, creditorListParams) if err != nil { fmt.Printf("error in fetching creditors: %s", err.Error()) } // The Creditors API returns a list of creditors, but any GoCardless account connected // to your application will have a single creditor, so you can just look at the first one creditor := creditors[0] if creditor.VerficationStatus == "action_required" { // We'll see below how to redirect users to the onboarding flow, and how it works redirectUserToOnboardingFlow() } } ``` > **Tip:** > You probably won't want to poll the Creditors API on every page load for your user's > `verification_status`. We'd recommend caching this and refreshing it regularly, as well as at > times when it makes sense in your user journey (for example when a user returns to your app > through the post-onboarding URL). A creditor's verification status will be one of these three values: ### Creditor Verification Statuses | **Status Value** | **What it Means** | **What Your App Should Do** | | ----------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | | `successful` | They are all set and fully verified. | Nothing. They can collect payments and receive payouts! | | `in_review` | They have sent all required information, and GoCardless is reviewing it. | They can't collect or get payouts yet. **Do not redirect them**. Just show a message letting them know it's being reviewed. | | `action_required` | We need more information to complete their verification. | You should immediately redirect them to the dedicated onboarding flow. | Users might revert back to `in_review` or `action_required` even after being `successful` (like if they change their bank account). Always check the status before allowing payment or payout features. We highly suggest adding clear messages in your UI if they are not `successful` (telling them why they can't collect/get paid) and pointing them to the onboarding flow if they're in `action_required`. ## Sending your user to the onboarding flow If the user's status is `action_required`, you need to send them to the dedicated GoCardless onboarding flow so they can provide the missing details. ### Onboarding Flow URLs | **Environment** | **URL** | | --------------- | ------------------------------------------------------------------------------- | | Sandbox | [https://verify-sandbox.gocardless.com](https://verify-sandbox.gocardless.com/) | | Live | [https://verify.gocardless.com](https://verify.gocardless.com/) | There, the user will fill in all the necessary information about themselves, their business, and their bank details. Once they're done, they _might_ see an option to head back to your app. This happens only if two things are true: 1. You have set a **post onboarding URL** in your app settings. 2. The user is connected to **just your app**. You can set the post-onboarding URL in the app creation or editing forms. If you're all set up, you can find the current URL on your app details page. ![Screenshot of the edit partner app form, with the post onboarding URL field highlighted](/images/docs/partner-integrations/getting-your-users-verified/edit_partner_app.png) ![Screenshot of the partner app details page, with the post onboarding URL section highlighted.](/images/docs/partner-integrations/getting-your-users-verified/app_details.png) When they complete the flow, they'll see a screen that offers a convenient way to return to your app (but note, it's not an automatic redirect). ![Screenshot of the 'back to your app' button a user sees at the end of the verification flow.](/images/docs/partner-integrations/getting-your-users-verified/back_to_app.png) > **Info:** > If the user is connected to more than one app (or none at all), they'll just see a generic button > to return to their GoCardless dashboard homepage. We don't have a way to know where they came from > in that case. When your user lands back in your product, it's likely that their verification status will not yet be `successful`. Some of the information provided by users requires review by GoCardless, so it may be a little while before they move to the `successful` state. Or in some cases, further information will be requested, meaning they'll move back to `action_required`. Once you see that they're in that `successful` state and you're all done with this part, you're ready to move on to the next step: helping them to start collecting payments and getting paid! > **Tip: Spot unverified merchants at a glance** > The [Partner Dashboard](https://manage.gocardless.com/) surfaces each merchant's verification > status in the Connected Merchants list, so you can see who still needs to complete onboarding. > Click "Switch to Partner View" in the side nav to access it. ## What's Next? #### [Set up mandates](/docs/partner-integrations/setting-up-mandates) Create Direct Debit mandates on behalf of your merchant's customers. #### [Webhooks for partners](/docs/partner-integrations/webhooks-for-partners) Listen for real-time events on mandates, payments, and billing requests. ## Go-live Checklist URL: https://docs.gocardless.com/docs/partner-integrations/go-live-checklist > Take your partner integration live with GoCardless. # Going Live with your integration Having followed our guides and built and tested your integration, check out our [best practices guide](/docs/partner-integrations/integration-guide) — it'll take you through everything you need to build a great integration for your users, and is perfect to review before you go live. ## Go-live checklist Before going live, a member of our GoCardless team will need to review your integration with a demonstration video. Your demo should provide a full walkthrough of the following key elements, using an additional sandbox account as if you were one of our mutual customers: ### 1. OAuth Including sign-in view, sign-up view, pre-filling capabilities, account connection, and clear verification or pending status. - [ ] Sign-in view - [ ] Sign-up view - [ ] Are you pre-filling merchant details? - [ ] Are you displaying whether the account is connected? - [ ] Are you displaying the GoCardless account status? ### 2. Mandates Demonstrate either hosted payment pages or custom pages (which will require compliance review) and pre-filling of customer and bank details. - [ ] If you're using custom payment pages, submit these for compliance review. - [ ] Are you pre-filling the customer details in the mandate? - [ ] Are you pre-filling the customer bank details in the mandate? ### 3. Payments Show usage of Payments, Subscriptions, and Instalments endpoints, including Open Banking and combined Open Banking/Direct Debit functionalities, and outbound payments. - [ ] Tell us which of the following endpoints you have implemented: - [Payments](/docs/api-reference/payment) - [Subscriptions](/docs/api-reference/subscription) - [Instalments](/docs/api-reference/instalment-schedule) - [ ] Have you implemented Open Banking? - [ ] Have you combined Open Banking and Direct Debit? - [ ] Have you built [Success+](/docs/optimise/reduced-failed-payments-with-success-plus)? - [ ] Have you built [Protect+](/docs/optimise/prevent-fraud-with-protect-plus)? - [ ] Have you integrated [Outbound Payments](/docs/partner-integrations/sending-money)? ### 4. Refunds Exhibit implemented refund capabilities. To enable refunds in sandbox, provide the partnerships team with the email address you used to create the account. - [ ] Have you implemented refund capabilities? ### 5. Reconciliation Display how current mandate and payment statuses are shown, and confirm that payments are marked as confirmed upon receiving the `payment_confirmed` event. - [ ] Where do you display the current mandate status? - [ ] Where do you display the current payment status? - [ ] Do you mark payments as confirmed upon receiving the `payment_confirmed` event? ## Submit your app for review Once you've fully tested your integration in the sandbox and recorded the demonstration video, a member of the GoCardless team will review it before you can start connecting merchants in the live environment. Make sure you have the following ready: - [ ] [Set up your live account](https://manage.gocardless.com/signup) - [ ] [Created your live app](https://manage.gocardless.com/partners/apps/create) - [ ] Recorded your demonstration video - [ ] Written a user guide explaining how your integration works, with the URL ready to share - [ ] A high-resolution logo so we can list you as [one of our partners](https://gocardless.com/partners) Send everything to [partnerships@gocardless.com](mailto:partnerships@gocardless.com) or your account manager. We'll aim to get back to you within 5 working days. To drive usage once you're live: - Develop a landing page with the key benefits of your GoCardless integration. - Write a user guide and include GoCardless in your FAQs and support materials. - Point users to it in welcome emails and regular communications. ## Earning money from your integration GoCardless offers a 10% revenue share of the transaction fees generated by your integration. For every transaction your users take through your integration, you'll receive a 10% share of the fees GoCardless collects. > **Warning:** > If you have chosen to apply app fees to your integration, you cannot also receive a revenue share. For more information or to set up a revenue share, contact the [partnerships team](https://gocardless.com/contact-sales/?s=partners). ## What's Next? #### [Integration guide](/docs/partner-integrations/integration-guide) Review the full best-practices checklist to ensure your integration is production-ready. #### [Partner integrations overview](/docs/partner-integrations) Return to the overview of all partner integration guides. ## Importing Outbound Payments URL: https://docs.gocardless.com/docs/partner-integrations/importing-outbound-payments > Import outbound payments for your partner integration with GoCardless. # Importing outbound payments > **Info:** > Currently, Outbound Payments APIs are limited to the UK and operate solely through the Faster > Payments scheme. The Outbound Payment Import API lets you create a batch of outbound payments in a single API call, then have your merchant approve the entire batch through the GoCardless dashboard. This is designed for partner integrations and removes two requirements that apply to [individual outbound payments](/docs/partner-integrations/sending-money). - **No API request signing** — import endpoints do not require request signing. - **No per-payment approval** — the merchant approves all payments in the batch at once, instead of approving each payment individually. ## Prerequisites Before creating an import, ensure the following are in place: - Your merchant must be fully onboarded with GoCardless and have Outbound Payments enabled at the merchant level. - The merchant's [payment account](/docs/send-money/payment-account) must be funded with a sufficient balance to cover the total import amount. - Recipient bank accounts must already exist for each payee — see [Create a recipient](/docs/send-money/send-an-outbound-payment/add-a-new-recipient) - The person authorising the import on the dashboard must have a GoCardless Dashboard user account with read-write or admin permissions and SMS-based two-factor authentication enabled. - You must have a valid access token for the merchant — see [Making API calls on behalf of your merchant](/docs/partner-integrations/sending-money#making-api-calls-on-behalf-of-your-merchant). ## How it works The import workflow has four stages: #### [1. Create the import](#create-the-import) Submit all payment entries in a single API call. GoCardless begins validating entries and running bank account holder verification checks. #### [2. Wait for validation](#wait-for-validation) Poll the API until all entries have been validated and verification checks are complete. #### [3. Authorise the import](#authorise-the-import) Share the authorisation link with your merchant. They review and approve the batch via the GoCardless dashboard using SMS-based SCA. #### [4. Track the result](#track-the-result) Each entry is automatically converted into an outbound payment. Use webhooks to track the status of each payment. ![Partners -> Outbound payment import -> Outbound payment import state machine](/images/docs/partner-integrations/importing-outbound-payments/outbound_payment_import_state_machine.png) ### Import statuses | Status | Description | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `created` | The import has been received. | | `validating` | Entry validation and bank account holder verification are in progress. | | `valid` | All entries passed validation and verification checks are complete. Ready for approval. | | `invalid` | One or more entries failed validation. The import cannot be authorised. | | `processing` | Approval received. Payments are being created. | | `processed` | All entries have been converted into outbound payments. | | `cancelled` | The import was cancelled. Unused imports expire after 3 calendar days. Imports abandoned during approval are cancelled within 5 minutes of the approval starting (when we send the SMS). | ## Create the import > **Warning:** > Imports are capped at **1000 entries**. If you need to send more payments, create multiple > imports. Submit a [Create an outbound payment import](/docs/api-reference/outbound-payment-import) request with an array of payment entries. For information on the entry parameters, please refer to the API reference linked. > **Tip: Action** > Call the [Create an outbound payment import](/docs/api-reference/outbound-payment-import) > endpoint. The top-level `links.creditor` field is optional. If omitted, the creditor is inferred from the access token used to make the request. You can set it explicitly when calling on behalf of a specific merchant. The response includes: - **`authorisation_url`** — The link to the GoCardless dashboard where the merchant reviews and authorises the import. Save this URL — you will share it with the merchant in [Step 3](#authorise_the_import). - **`status`** — Initially `validating` while GoCardless checks each entry and runs bank account holder verification. - **`entry_counts`** — A summary of validation and verification results, updated as checks complete. ## Wait for validation After creation, GoCardless validates each entry and runs [bank account holder verification](/docs/send-money/bank-account-holder-verification) checks. The import remains in `validating` status until all checks are complete, then transitions to `valid` or `invalid`. There are no webhook notifications for import status changes. You must poll the API to check when validation completes. Validation takes about half a minute to a minute. > **Tip: Action** > Poll the [Get an outbound payment import](/docs/api-reference/outbound-payment-import) endpoint > until the status changes from `validating`. When validation and verification checks are complete, the response will show the updated status and verification counts: ```http HTTP/1.1 200 OK Content-Type: application/json { "outbound_payment_imports": { "id": "IM123", "created_at": "2024-09-05T12:20:04.397Z", "status": "valid", "amount_sum": 3500, "currency": "GBP", "authorisation_url": "https://manage.gocardless.com/imports/IM123", "entry_counts": { "total": 2, "valid": 2, "invalid": 0, "verified": 2, "verified_with_full_match": 1, "verified_with_partial_match": 1, "verified_with_no_match": 0, "verified_with_unable_to_match": 0, "processed": 0, "failed_to_process": 0 }, "links": { "creditor": "CR123" } } } ``` ### Bank account holder verification Bank account holder verification runs automatically during validation. The `entry_counts` object on the import provides a summary of results: | Field | Meaning | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `verified` | Total number of entries verified. | | `verified_with_full_match` | The recipient's name fully matches the name on the bank account. | | `verified_with_partial_match` | The recipient name is a close but not an exact match. | | `verified_with_no_match` | The recipient's name does not match the name on the bank account. | | `verified_with_unable_to_match` | The verification could not return a definitive result. This is because the recipient's bank does not support the verification check, or the verification service is unavailable. | Verification results do not block an import from reaching `valid` status. Even entries with a `no_match` result can proceed — the verification results are displayed on the dashboard during authorisation, so the approver can make an informed decision. You can also retrieve individual verification results by using the [List outbound payment import entries](/docs/api-reference/outbound-payment-import-entry) endpoint. Each entry in the response includes a `verification_result` field with one of: `full_match`, `partial_match`, `no_match`, `unable_to_match`, or `null` (if verification has not yet been completed). For more details, see [Bank account holder verification](/docs/send-money/bank-account-holder-verification). ## Authorise the import Once the import reaches `valid` status, it must be authorised through the GoCardless dashboard. The `authorisation_url` from the import creation response is a standard web link. You can present it in your application as a redirect or new window, or share it via email or a notification in your platform. > **Tip: Action** > Share the `authorisation_url` with the user who will authorise the import. > **Warning:** > Imports that are not authorised within **3 calendar days** of creation are automatically > cancelled. ### What the approver sees When the approver visits the authorisation link, they sign in to the GoCardless dashboard and are taken to the import review pages. ### 1. Sign in to GoCardless The approver enters their GoCardless dashboard credentials. ![Screenshot: Sign in page](/images/docs/partner-integrations/importing-outbound-payments/screenshot_2026-03-30_at_12.46.09.png) ### 2. Review the import summary The import process page displays a summary of the import, including the total number of payments, the total value, the available balance on the source payment account, and a breakdown of bank account holder verification results by category. ![Partners -> Outbound payment imports -> Screenshot: Process](/images/docs/partner-integrations/importing-outbound-payments/screenshot_2026-03-30_at_13.04.17.png) ### 3. Review individual entries From the summary page, the approver can click through to review individual entries. This page shows a paginated table of all entries with the amount, recipient, reference, and bank account holder verification result for each. ![Partners -> Outbound payment imports -> Screenshot: entry table](/images/docs/partner-integrations/importing-outbound-payments/screenshot_2026-03-31_at_15.45.19.png) ### 4. Complete SCA and approve When satisfied, the approver clicks approve. GoCardless sends an SMS code to their registered phone number. Entering the code completes SCA and authorises all payments in the import — they are submitted immediately and do not require separate approval. ![Partner -> Outbound payment imports -> Screenshot: SCA dialog](/images/docs/partner-integrations/importing-outbound-payments/screenshot_2026-03-30_at_13.08.43.png) ![Partners -> Outbound payment imports -> Screenshot: payments submitted](/images/docs/partner-integrations/importing-outbound-payments/screenshot_2026-03-30_at_13.11.16.png) > **Warning:** > Authorisation is all-or-nothing. You cannot approve or reject individual entries within an import. > If any entries need to be corrected or removed, you must create a new import without those > entries. ## Track the result After authorisation, the import moves through `processing` to `processed`. The import counts will contain `processed` and `failed_to_process`, indicating whether all payments were created successfully. To track the progress of the created payments, it is recommended to use webhooks. ### Check processing status > **Tip: Action** > Poll the [Get an outbound payment import](/docs/api-reference/outbound-payment-import) endpoint > until `status` is `processed`. ```http GET https://api.gocardless.com/outbound_payment_import_entries?import=IM123 HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json { "outbound_payment_import_entries": [ { "id": "IE123", "created_at": "2024-09-05T12:20:04.397Z", "processed_at": "2024-09-05T12:35:10.000Z", "entry_number": 1, "amount": 1000, "scheme": "faster_payments", "reference": "INV-001", "verification_result": "full_match", "validation_errors": null, "links": { "import": "IM123", "outbound_payment": "OUT00456", "recipient_bank_account": "BA0001234" } }, { "id": "IE124", "created_at": "2024-09-05T12:20:04.397Z", "processed_at": "2024-09-05T12:35:10.000Z", "entry_number": 2, "amount": 2500, "scheme": "faster_payments", "reference": "INV-002", "verification_result": "partial_match", "validation_errors": null, "links": { "import": "IM123", "outbound_payment": "OUT00457", "recipient_bank_account": "BA0005678" } } ], "meta": { "cursors": { "before": null, "after": null }, "limit": 50 } } ``` ### Track the progress of created payments > **Tip: Action** > Set up [webhooks](/docs/api-reference/webhooks) using [this getting started > guide](/docs/getting-started/stay-up-to-date-with-webhooks). This is the recommended way of > tracking the state of individual payments. Once individual outbound payments are created from an import, they follow the standard [outbound payment lifecycle](/docs/send-money/tracking-outbound-payments) and generate webhook events as their status changes. Each outbound payment includes the ID of the import that created it in `links.outbound_payment_import`. Alternatively, list outbound payment import entries using the [List outbound payment import entries](/docs/api-reference/outbound-payment-import-entry) endpoint. The `links.outbound_payment` field on each entry contains the ID of the created outbound payment. This ID can be used to track individual payment statuses through the standard [outbound payment APIs](/docs/send-money/tracking-outbound-payments). ## Handling invalid imports If any entry fails validation, the entire import transitions to `invalid` and cannot be authorised. To identify the errors and recover: 1. List the import's entries using the [List outbound payment import entries](/docs/api-reference/outbound-payment-import-entry) endpoint. 2. Check the `validation_errors` field on each entry for per-field error details. 3. Fix the issues in your data. 4. Create a new import with the corrected entries. An entry with validation errors looks like this: ```json { "id": "IE125", "created_at": "2024-09-05T12:20:04.397Z", "processed_at": null, "entry_number": 3, "amount": null, "scheme": null, "reference": null, "verification_result": null, "validation_errors": { "outbound_payment": { "amount": ["must be greater than 0"], "scheme": ["is not included in the list"] } }, "links": { "import": "IM124", "outbound_payment": null, "recipient_bank_account": "BA0009999" } } ``` The `validation_errors.outbound_payment` object contains error messages keyed by field name: `amount`, `scheme`, `recipient_bank_account`, or `reference`. > **Warning:** > Invalid imports cannot be partially processed or edited. You must create a new import with > corrected entries. ## Monitoring your imports Use the [List outbound payment imports](/docs/api-reference/outbound-payment-import) endpoint to check `status` and see whether an import is ready to be approved. Use the [List outbound payment import entries](/docs/api-reference/outbound-payment-import-entry) endpoint to inspect individual entries, including any `validation_errors` on an `invalid` import. ## Expiry and cancellation Imports in `valid` status that are not authorised within **3 calendar days** of creation are automatically cancelled by the system. There is no API endpoint to cancel an import. If you need to discard an import, create a new one and let the old one expire. Once an import is cancelled — whether by expiry or otherwise — it cannot be reactivated. Create a new import instead. ## What's Next? #### [Webhooks for partners](/docs/partner-integrations/webhooks-for-partners) Track payment and import status changes in real time with webhook events. #### [Send money](/docs/partner-integrations/sending-money) Initiate individual outbound payments on behalf of your merchants. ## Integration Guide URL: https://docs.gocardless.com/docs/partner-integrations/integration-guide > Checklist and guide for building a complete partner integration. # Integration Guide ## Best practices We want to help you build a great integration that delivers real value to your users. Work through this checklist before going live to make sure you've covered everything. ### Setup ### Account set up **Have you given your app a sensible, public-facing name?** - Your users will see this when they grant you access to their GoCardless accounts through the OAuth flow, and it'll appear in our reporting. **Have you verified your account for payouts?** - This is important if you are receiving a revenue share or adding app fees, as we cannot pay those out otherwise. **Have you added contact details to your account?** - Your contact details are displayed to your clients, so make sure they're up to date. **Are you based in the same country as your merchants?** - If you are in the UK, Bacs will be enabled by default. If you are in the Eurozone, SEPA will be enabled by default. - You may need to [contact our API support team](mailto:api@gocardless.com) to enable the right scheme on your account. **Have you checked the Partner Dashboard to confirm your merchants are connected and active?** - The [Partner Dashboard](https://manage.gocardless.com/) gives you a live view of connected merchants, their verification status, and integration health. Click "Switch to Partner View" in the side nav to access it. ### Merchant onboarding **Are you using OAuth to get access to your users' accounts?** - [OAuth](/docs/partner-integrations/connect-your-merchants) allows a merchant to easily and securely give you access to their account so you can use the GoCardless API on their behalf. **Are you passing the `initial_view` parameter when you create an OAuth link?** - You can specify whether the OAuth flow should default to showing a login screen or a signup screen. **Are you prefilling merchants' email addresses?** - If you already know your merchant's email address, prefill the OAuth flow using the `prefill[email]` parameter. You can also prefill their given and family names, and their organisation name. **Have you made it clear that merchants will need to verify their accounts before they can receive payouts?** - Before a merchant can receive payouts, they need to go through GoCardless's onboarding and verification process. - Using the API, you can check your users' verification state and send them to the onboarding flow if required. - GoCardless will also send your users email notifications reminding them to verify their account. **Have you made it easy to configure the merchant's account once they've connected? For example, can they configure:** - When payments should be collected? - How mandates are set up? - Any reconciliation settings? **If you are charging app fees, is it clear to merchants how much?** ### Mandates ### Mandate configuration **Is it easy for merchants to request customers to set up mandates?** - Can merchants send requests to multiple customers in batch? **Can the merchant clearly see which customers have set up a mandate?** - Are you listening to our webhook events and actions? **Can the merchant send reminders to customers to set up mandates?** - A customer might miss the notification to create a mandate — it's good practice to allow sending a reminder after some time has passed. - Can you automate reminders? **What happens if the mandate fails to be set up?** - Do you inform your user? Do you re-open the invoice? - Do you help your user understand what went wrong? [(more details)](/docs/api-reference/events/mandate) **What happens if the mandate is cancelled?** - Do you tell your user? - Do you provide a way to reinstate the mandate? - Do you help your user understand what went wrong? [(more details)](/docs/api-reference/events/mandate) **What happens if the mandate expires?** - Do you tell your user? - Can you reinstate the mandate? **Can an existing GoCardless merchant import their mandates and match them to customers?** - If yes, do you check whether merchants have subscriptions or plans set up? These may need to be cancelled — [contact our API support team](mailto:api@gocardless.com) for help. - Find out how to [list all](/docs/api-reference/mandate#list-mandates) or [retrieve a single mandate](/docs/api-reference/mandate#get-a-single-mandate). - Find out how to [list subscriptions](/docs/api-reference/subscription#list-subscriptions). **Can you manage bulk changes (transfers of existing Direct Debits from another provider)?** - [Contact our API support team](mailto:api@gocardless.com) if you want to implement bulk changes. **If you offer multiple payment options, how do you refer to your GoCardless integration?** - Make sure to refer to it as 'pay by Direct Debit' (or the corresponding local scheme name). - List the GoCardless payment methods, such as 'Pay By Bank' and 'Direct Debit'. ### Hosted Payment Pages OptionalWhen using the [payment pages hosted by GoCardless](/docs/collect-payments/setting-up-mandates): **Is it intuitive for end customers to set up mandates?** - Do you include instructions or payment links in emails? - Do you link to the payment pages from invoices? How does this work for future payments? - Do you link to the payment pages from your website? **Are you using the description parameter to show a description of what the end customer is signing up for?** - You can set the description when creating a [redirect flow](/docs/api-reference/redirect-flow#create-a-redirect-flow). - Are you allowing your customers to pre-fill the mandate with customer and billing information if available? **Does your redirect URL (after setting up a mandate) look great for an end customer?** - Does it make clear that Direct Debit is set up? - Does it describe what happens next — for example, when the customer will be charged? ### Custom Payment Pages OptionalMerchants on the **Pro/Custom** package can request custom payment pages. **If you or your merchants use custom payment pages:** - Have your merchant's payment pages been reviewed by GoCardless? - Do you make it easy for merchants to create end customers with GoCardless by handling that for them? **If you support setting up mandates by phone:** - Has the script been reviewed and will calls be recorded? - Are you doing modulus checking using the [Bank Details Lookups API](/docs/api-reference/bank-details-lookup)? **If your merchant is passing you bank details, are you doing modulus checking?** - Modulus checking is used to do basic validity checking of bank details. - Use the [Bank Details Lookups API](/docs/api-reference/bank-details-lookup). ### Mandate transfers **Are you aware that we only expose the last 2 digits from a bank account when a customer switches bank accounts?** - For security reasons, we only expose the last 2 digits of bank account information via API. - We'll send a "transferred" webhook when a customer switches bank accounts [(more details)](/docs/api-reference/events/mandate). - You can retrieve limited details about an end customer's bank account via the API [(more details)](/docs/api-reference/customer-bank-account). - With the Encrypted Bank Details Access upgrade you can retrieve the full bank details via the API [(more details)](/docs/gc-embed/bank-details-access). ### Payments ### Payment collection **Have you implemented all the available payment methods that GoCardless provides?** - Open banking [(more details)](/docs/collect-payments/one-off-payments/pay-by-bank). **[Mandatory]** - Direct Debit [(more details)](/docs/collect-payments/setting-up-mandates). **[Mandatory]** - Combining a one-off payment and Direct Debit [(more details)](/docs/collect-payments/recurring-payments/instant-first-payment-with-mandate). **[Highly Recommended]** **How are you creating payments — individual requests or subscriptions?** - If you're creating one-off payments, be aware that notifications will be sent for each payment (depending on the merchant notification settings). **Can the merchant create a payment as soon as a customer has set up a mandate?** - You don't need to wait until the mandate is active. **Do you allow merchants to schedule payments in advance?** - When creating payments, you can specify an optional `charge_date` [(more details)](/docs/api-reference/payment#create-a-payment). **Do you enable merchants to collect both one-off and recurring payments?** [(more details)](/docs/collect-payments/one-off-payments/pay-by-bank) **For single one-off payments, do you store our mandate ID?** - Storing the mandate ID lets you connect a customer in your database with the mandate on GoCardless, enabling future payments without the customer re-entering bank details. **Are you aware of our maximum £5k limit per transaction?** - [Contact our partnerships team](https://gocardless.com/contact-sales/?s=partners) for details. **Are you aware of our minimum £1 limit per transaction?** - [Contact our partnerships team](https://gocardless.com/contact-sales/?s=partners) for details. **Do you allow merchants to retry payments that fail?** [(more details)](/docs/api-reference/payment#retry-a-payment) - Payments can be retried up to 3 times. - You should only retry payments that fail due to insufficient funds. - Have you factored in Success+ intelligent payment retries? [(more details)](/docs/optimise/reduced-failed-payments-with-success-plus) **What happens when payments fail?** - Do you notify the merchant? - Do you tell them why it failed? - Do you reopen the invoice? - Do you give an option to retry the payment (or automate this)? **Do you use idempotency keys to avoid duplicate payments?** [(more details)](/docs/api-reference/limits#idempotency-keys) - You can safely retry creating payments by using idempotency keys. - Our client libraries allow you to set idempotency keys when creating resources. **Are you charging app fees?** [(more details)](/docs/partner-integrations/connect-your-merchants) - Make sure that app fees are never more than 50% of any given payment amount. ### Refunds Mandatory**Do you need refunds enabled for your users?** - This is available for all customers who request this feature. **Are you aware that you can trigger refunds via the API?** [(more details)](/docs/api-reference/refund#create-a-refund) **Are you aware that we can only refund against a specific transaction?** - This means a refund shouldn't be used for general payouts like goodwill credits. **Are you making sure to only enable refunds at least 2 days after the customer is charged?** - This avoids refunding a payment that later fails. - Note that the 7-day safer refund process is enabled by default — customers cannot refund until 7 days have passed (this can be switched off on request). **Do you know that we can still refund a payment even after the mandate has been cancelled?** ### Payouts and reconciliation **How are you handling reconciliation when we pay out to your user?** [(more details)](/docs/collect-payments/managing-payments/reconciling-payouts) - Do you mark the corresponding invoice as paid? - Are fees (included in payouts) shown and posted as expenses? - Are you marking the payment as paid upon receiving the `payment_confirmed` event? **[Highly Recommended]** [(more details)](/docs/api-reference/events/payment) - Are you updating the invoice as paid_out upon receiving the `paid_out` event? **[Recommended for reconciliation]** [(more details)](/docs/api-reference/events/payment) ### Going live ### Testing in a sandbox environment Highly Recommended**Have you tested your integration in [the sandbox](https://manage-sandbox.gocardless.com/sign-up) before going live?** - In the sandbox, you can test without real money changing hands. We provide test bank details to make it as simple as possible [(more details)](/docs/developer-resources/test-bank-details). - The sandbox lets you manually trigger cases like a customer cancelling their mandate or a payment failing due to insufficient funds [(more details)](/docs/developer-resources/scenario-simulators). **Have you connected a separate GoCardless account to your app?** - To mirror a separate merchant connecting to your app, test with a separate account. - Ensure you aren't using real email addresses in the sandbox, as this will send notifications. **Have you tested payments with your live account?** - After successfully testing in the sandbox, test in live to make sure everything works as expected. **Have you tested the redirect URL flow?** - GoCardless partner apps can have up to twenty redirect URLs, which is useful for testing across development, QA, and other environments. ### Error handling **How does your integration handle API errors?** - Our [API reference](/docs/api-reference/responses-and-errors) includes details on errors returned by the API and how to handle them. **Are you aware of our API rate-limiting?** - This might be relevant if you have very high volume merchants. See our [API reference](/docs/api-reference/limits#rate-limiting) for details. ### GoCardless brand Recommended**Are you using the correct GoCardless logo?** - Have a look at the [GoCardless branding page](https://brand.gocardless.com/) for up-to-date logos. ### Promoting the integration **Is it clearly visible how to sign up to GoCardless? For example:** - If you have created a payments tab, link to your GoCardless integration from there. - Add an alert to your homepage. - Add relevant in-product prompts, for example when merchants create an invoice or sign a contract. - Embed or promote setting up payments as part of the new user onboarding experience. - Include relevant information and links in welcome emails and regular communications. - Create a landing page with benefits. - Document your GoCardless integration in the user guide and make it easy to find. - Add information on your GoCardless integration in the FAQs and help section. ## What's Next? #### [Go-live checklist](/docs/partner-integrations/go-live-checklist) Complete the steps required to move your integration from sandbox to production. #### [UX guides & resources](/docs/partner-integrations/ux-guides-and-resources) Follow UX best practices for surfacing GoCardless in your product. ## Partner Dashboard URL: https://docs.gocardless.com/docs/partner-integrations/partner-dashboard > Monitor your connected merchants, debug payments, and manage your app configuration from the GoCardless Partner Dashboard. # Partner Dashboard The Partner Dashboard is a self-serve view inside the GoCardless dashboard that lets you monitor your integration, see how your merchants are performing, and debug payment issues. ## Getting access You'll need to be part of an organisation with a live or sandbox partner app to access the Partner Dashboard. 1. Go to [manage.gocardless.com](https://manage.gocardless.com/) 2. Click **"Switch to Partner View"** in the side nav If you don't see the option, ask your GoCardless admin to invite you via **Settings > Team**. ## What you can do - View integration-wide metrics: payment volume, failure rate, active and connected merchant counts - See every merchant connected via your OAuth integration, their verification status, and activity - Drill into a merchant to view their payers, payments, and payouts - Check the full timeline and webhook delivery status for any payment, and retry a failed webhook in one click - View and update your app's OAuth and webhook configuration in **App details** > **Info:** > The Partner Dashboard shows self-serve revenue share data only. For revenue share of merchants on > committed contracts, contact your Partner Account Manager. ## Further reading For a full walkthrough of each page, see the [Partner Dashboard FAQ](https://support.gocardless.com/hc/en-gb/articles/28642300142748-Partner-dashboard-FAQ) in the GoCardless Help Centre. ## What's Next? #### [Webhooks for partners](/docs/partner-integrations/webhooks-for-partners) Set up webhook handlers for real-time payment and mandate events. #### [Go-live checklist](/docs/partner-integrations/go-live-checklist) Complete the steps required to move your integration from sandbox to production. ## Sending Money URL: https://docs.gocardless.com/docs/partner-integrations/sending-money > Send payments to your users or their customers as a partner. # Send Money You'll need to provide a way for your merchants to initiate outbound payments so they can send money to their chosen recipients. > **Info:** > Currently, Outbound Payments APIs are limited to the UK and operate solely through the Faster > Payments scheme. ## Prerequisites for Outbound Payments Before you can start sending money through GoCardless, make sure the following are in place: - Your merchants must be fully onboarded with GoCardless. - Outbound Payments must be enabled for each merchant. This setting is applied at the merchant level, so even if you - as a partner - have Outbound Payments enabled, you won't be able to create outbound payments on a merchant's behalf unless it's enabled for them too. - Anyone in your merchants' organisations who will be sending money needs their own GoCardless Dashboard user account with read-write/admin permissions. - These users must also have SMS-based 2FA turned on to be able to receive payment authorisation codes. ## How it works The Outbound Payments API allows you to initiate payouts from a merchant's bank account to a recipient. Instead of building complex compliance flows yourself, GoCardless handles the regulatory heavy lifting, including **Strong Customer Authentication (SCA)** and **Confirmation of Payee (CoP)** through an API response model. The flowchart below provides a **high-level overview** of the Outbound Payment Initiation process from partner apps: ![Image: Outbound Payments For Partners -> Flow](/images/docs/partner-integrations/sending-money/flowchart.png) The overall flow consists of the following stages: #### [1. Authenticate](#making-api-calls-on-behalf-of-your-merchant) Ensure your merchant has Outbound Payments enabled and use their unique access token to make API requests. #### [2. Initiate the payment](#outbound-payment-initiation) Call the Create Outbound Payment API, which performs CoP and automatically determines whether SCA is required. #### [3. Handle outcomes](#handling-outcomes) Handle three possible outcomes: an immediate `201 Created`, a `403` requiring dashboard redirect, or a validation error. #### [4a. Redirect (SCA required)](#what-happens-after-redirect) Redirect the user to the GoCardless Dashboard to review payment details and enter an SMS code. #### [4b. Complete payment (SCA exempt)](#outbound-payment-completion) Display CoP results and call the Approve Outbound Payment API to send the payment. ## Making API Calls on behalf of your merchant You must have gotten and saved merchants' access tokens after [following the OAuth flow](/docs/partner-integrations/connect-your-merchants#using-the-oauth-flow). To make an API call against a merchant's account, use the saved access token. See an example below: ```php $user->gocardlessAccessToken, // Change me to LIVE when you're ready to go live 'environment' => \GoCardlessPro\Environment::SANDBOX ]); ``` ```python import os import gocardless_pro client = gocardless_pro.Client( # You'll need to identify the user that the customer is paying # and fetch their access token access_token=user.gocardless_access_token, # Change this to 'live' when you are ready to go live. environment='sandbox' ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( # You'll need to identify the user that the customer is paying # and fetch their access token access_token: user.gocardless_access_token, # Remove the following line when you're ready to go live environment: :sandbox ) ``` ```java package com.gcintegration; import com.gocardless.GoCardlessClient; import com.gocardless.resources.RedirectFlow; GoCardlessClient client = GoCardlessClient // You'll need to identify the user that the customer is paying // and fetch their access token .newBuilder(CurrentUser.gocardlessAccessToken) // Change me to LIVE when you're ready to go live .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const client = gocardless( // We recommend storing your access token in an environment // variable for security user.GoCardlessAccessToken, // Change this to constants.Environments.Live when you're ready to go live constants.Environments.Sandbox, ); ``` ```net using GoCardless; GoCardlessClient client = GoCardlessClient.Create( // We recommend storing your access token in an // configuration setting for security User["GoCardlessAccessToken"], // Change me to LIVE when you're ready to go live GoCardlessClient.Environment.SANDBOX ); ``` ```go package main import ( "fmt" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { accessToken := user.accessToken config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } } ``` ## Outbound Payment Initiation To initiate outbound payment, use either the [Create Outbound Payment API](/docs/send-money/send-an-outbound-payment/create-an-outbound-payment) or the [Create Withdrawal API](/docs/send-money/send-an-outbound-payment/create-an-outbound-payment). Refer to the [create a recipient guide](/docs/send-money/payment-account) and the [outbound payment types guide](/docs/send-money/send-an-outbound-payment/create-an-outbound-payment) for details on required parameters. When you're initiating outbound payments from an app, the key thing to be aware of is how **Confirmation of Payee (CoP)** and **Strong Customer Authentication (SCA)** work for you. UK regulations require UK Payment Service Providers to implement CoP. GoCardless automatically runs these checks for every outbound payment — read more about [verifications for Outbound Payments](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment). GoCardless is responsible for carrying out SCA, so we require your app to use our SCA solution. The regulations do allow a few exemptions, and at GoCardless, we support _Trusted Beneficiary_ — see [SCA exemptions](/docs/send-money/strong-customer-authentication) for more details. When a recipient with a full or partially matched CoP results receives their first payment with a successful SCA, they are added to a trusted list. This means future payments to this recipient will not trigger the GoCardless SCA flow. For your app, this means: - **Payments that qualify for an SCA exemption** can be initiated directly through the API without redirecting. - **Payments requiring SCA** must be initiated via a redirect to the GoCardless Dashboard so the user can complete authentication. > **Tip: Action** > Call Create Outbound Payment API or the Create Withdrawal API. ## Handling Outcomes ### Payment qualifies for an SCA exemption If the payment qualifies for an SCA exemption, it will be initiated immediately. You'll receive a `201 Created` response with the payment details, including its ID for [tracking the payment](/docs/send-money/tracking-outbound-payments). At this point the payment has been created — the [next step is to approve it](#outbound_payment_completion) so it can be sent. ### Payment requires SCA If the payment does not qualify for an SCA exemption, the API will return a `403 insufficient_permissions_continue_on_dashboard`. The error response includes a dashboard link containing all the outbound payment parameters you provided, along with an HMAC to ensure the data cannot be modified. > **Warning:** > Do not modify the dashboard link directly. If you need to change any payment parameters, you > must create a new API request to generate a fresh outbound payment with the updated values. ```http HTTP/1.1 403 Content-Type: application/json { "error": { "message": "Unauthorised to perform this action via the API due to compliance. Please continue via the dashboard.", "errors": [ { "reason": "insufficient_permissions_continue_on_dashboard", "message": "Unauthorised to perform this action via the API due to compliance. Please continue via the dashboard.", "links": { "dashboard": "https://manage.gocardless.com/send-payment/partner-app?amount=100&hmac=MIGHAkIAzLuSvWrCWk8b4g37%2FZgpd9sz8ksM9Sh6%2FcZUjgnkHVgKvqNuI8kMPYlm%2Bolo8ThTiwS3LAAuDxzhKGToOxvFcLICQWfJgKwqjjHt1I8LheV1tPgfv5A1J3z%2Flzaa8u40VSQWzPqB%2B5IIxjuPNCwdl1hEvXLx1PRkCl1M29uTtvYBM5dM&recipientBankAccount=BA0001238&scheme=faster_payments" } } ], "documentation_url": "/docs/api-reference/responses-and-errors#invalid-api-usage", "type": "invalid_api_usage", "request_id": "89a7f8ef-7159-4b4b-8d75-14d5885d3a0b", "code": 403 } } ``` Open the provided dashboard link in a new browser tab or window — CoP display and payment approval are handled there. Payment updates are communicated back to your app via the [postMessage Web API](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). See [what happens after redirect](#what_happens_after_redirect) and [handling postMessage events](#handle_events_from_redirect) for details. > **Tip: Action** > Redirect to the dashboard link. ### Errors If you receive an error **other than** `403 insufficient_permissions_continue_on_dashboard`, it usually means the payment parameters are invalid. GoCardless always returns validation errors first, before checking whether SCA is required. For example, if a payment contains invalid parameters, you'll receive a `422` error — fix the input before redirecting the user to the dashboard. ## Outbound Payment Completion In your app, make sure to show the CoP results to the user before they approve the payment. This helps them confirm that the payment is going to the correct recipient. Once the user has reviewed the CoP results and is ready to proceed, call the [Approve Outbound Payment API](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment) to submit the payment to the banks. > **Tip: Action** > Display CoP results for the user to review, then call the [Approve Outbound Payment > API](/docs/send-money/send-an-outbound-payment/approve-an-outbound-payment) to submit the payment. ## What happens after redirect Once your user is redirected to the dashboard link, they will see the _GoCardless Sign-In_ page. They must enter their GoCardless username and password. ![Image -> Sign In](/images/docs/send-money/strong-customer-authentication/screenshot_2025-10-02_at_15.28.22.png) After successfully logging in, the user will be taken to the _Outbound Payment Review_ page, where they can view the payment details provided by your app, along with the CoP results for the payment. ![Image: Outbound Payments -> Review](/images/docs/partner-integrations/sending-money/screenshot_2025-11-24_at_18.33.10.png) If the user is satisfied with the payment details, they can click "_Send payment_". They will then receive an SMS with an authorisation code, which they must enter to approve the payment. ![Image: Outbound Payments For Partners -> SCA dialog](/images/docs/partner-integrations/sending-money/screenshot_2025-11-24_at_18.38.01.png) Entering the code completes SCA and approves the payment. The payment will then be submitted shortly and recorded as originating from your app. ![Image: Outbound Payments For Partners -> Success](/images/docs/partner-integrations/sending-money/screenshot_2025-11-27_at_16.24.20.png) ## Handle events from redirect When your app opens a dashboard link in a new browser window or tab, the dashboard flow will send information back to your app using [window.opener.postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). #### Example: - Your app opens a new tab (e.g., a redirect link from GoCardless): ```javascript const gocardlessTab = window.open(gocardlessDashboardUrl, "\_blank"); ``` - The dashboard flow runs in that new tab. - When something happens (e.g., a payment is approved or errored), the dashboard sends a message back to your app: ```javascript window.opener.postMessage({ eventName: "success", payload: { outboundPaymentId: "OUT12345" }, }); ``` - Your app receives and handles the message using a message event listener. #### How to add a Message Listener in Your App: The GoCardless dashboard flow currently sends two types of events: - **"success"** means SCA was completed and the payment was created. The event payload includes the outbound payment ID, which you can use to track its status if needed. - **"failure"** can occur for several reasons, such as a failed or expired SCA or an error while creating the payment. In these cases, the dashboard flow will display an error screen explaining what went wrong. In the page that opened the new tab, add: ```javascript window.addEventListener("message", (event) => { // Validate the origin for security if (event.origin !== "https://manage.gocardless.com/") { return; } if (event.data.eventName === "success") { // Refresh UI, show success, etc. } if (event.data.eventName === "failure") { // Handle errors } }); ``` It's possible for a user to abandon the flow before completing it by closing the tab or popup window. Because `postMessage` cannot detect when a window is closed, you'll need to use window polling if you want to track and handle this scenario in your app: ```javascript const gocardlessTab = window.open(gocardlessDashboardUrl, "_blank"); // Check every 500ms whether popup was closed const timer = setInterval(() => { if (gocardlessTab.closed) { clearInterval(timer); console.log("GoCardless Flow tab was closed by the user."); // Handle as a cancellation or fallback } }, 500); ``` ## What's Next? #### [Import outbound payments](/docs/partner-integrations/importing-outbound-payments) Send batches of outbound payments for merchant approval via the GoCardless dashboard. #### [Webhooks for partners](/docs/partner-integrations/webhooks-for-partners) Track payment status changes in real time with webhook events. ## Setting Up Mandates URL: https://docs.gocardless.com/docs/partner-integrations/setting-up-mandates > Set up Direct Debit mandates on behalf of your users. # Setting up mandates ## Setting up Direct Debit mandates You'll need to provide a way for your users to set up Direct Debit mandates with their customers (whom we'll refer to from now on as **"end customers"**) so they can start collecting payments from them. A mandate allows you to pull money from an end customer's bank account with a simple API call. > **Info: Mechanisms to add customers** > We have three options for setting up Direct Debit mandates. [Read more about our different > solutions and view a comparison here](/docs/collect-payments/integration-planner). ## Sending merchants to your app Firstly - once a merchant completes verification, there are two ways they might make their way to your platform to start setting up payments: 1. Via the post-onboarding redirect - if you've configured a **post onboarding URL** in your App settings, GoCardless redirects the merchant there automatically after they finish verification. In this case they land directly on your platform can finish setting up their account with you and start setting up payments. 2. Via the GoCardless dashboard - some merchants will land on the GoCardless dashboard, either by navigating there directly or returning after verification. To handle this, you can set a **payment setup URL** in your App settings. This controls where the "Get started with payments" prompt in the dashboard takes them - it should link to the page on your platform where they can begin creating mandates and payments. _If no payment_setup_url is set, the prompt falls back to your post_onboarding_url, or your website_url if neither is configured._ ![Partner - dashboard setup payments](/images/docs/partner-integrations/setting-up-mandates/screenshot_2026-04-23_at_15.15.45.png) ![Partners - payment setup URL](/images/docs/partner-integrations/setting-up-mandates/screenshot_2026-04-23_at_15.26.43.png) ## Making API Calls on behalf of your merchant **Prerequisite:** We must have gotten and saved merchants' access tokens after following the steps [here](/docs/partner-integrations/connect-your-merchants#using-the-oauth-flow). To make an API call against a merchant's account, we will have to use the **saved access token**. See an example below: ```php $user->gocardlessAccessToken, // Change me to LIVE when you're ready to go live 'environment' => \GoCardlessPro\Environment::SANDBOX ]); ``` ```python import os import gocardless_pro client = gocardless_pro.Client( # You'll need to identify the user that the customer is paying # and fetch their access token access_token=user.gocardless_access_token, # Change this to 'live' when you are ready to go live. environment='sandbox' ) ``` ```ruby require 'gocardless_pro' client = GoCardlessPro::Client.new( # You'll need to identify the user that the customer is paying # and fetch their access token access_token: user.gocardless_access_token, # Remove the following line when you're ready to go live environment: :sandbox ) ``` ```java package com.gcintegration; import com.gocardless.GoCardlessClient; import com.gocardless.resources.RedirectFlow; GoCardlessClient client = GoCardlessClient // You'll need to identify the user that the customer is paying // and fetch their access token .newBuilder(CurrentUser.gocardlessAccessToken) // Change me to LIVE when you're ready to go live .withEnvironment(GoCardlessClient.Environment.SANDBOX) .build(); ``` ```javascript const constants = require("gocardless-nodejs/constants"); const client = gocardless( // We recommend storing your access token in an environment // variable for security user.GoCardlessAccessToken, // Change this to constants.Environments.Live when you're ready to go live constants.Environments.Sandbox, ); ``` ```net using GoCardless; GoCardlessClient client = GoCardlessClient.Create( // We recommend storing your access token in an // configuration setting for security User["GoCardlessAccessToken"], // Change me to LIVE when you're ready to go live GoCardlessClient.Environment.SANDBOX ); ``` ```go package main import ( "fmt" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) func main() { accessToken := user.accessToken config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } } ``` ### Collecting Payments Once you have the client set up with your merchant's access token, use a Billing Request Flow to set up Direct Debit mandates or Pay By Banks on their behalf. This handles the full payer experience — collecting bank details, authorisation, and confirmation. For a full walkthrough of Billing Request Flows and the payer journey, see [collecting payments](/docs/collect-payments). ## What's Next? #### [Webhooks for partners](/docs/partner-integrations/webhooks-for-partners) Learn about webhook events and how to handle them for your partner integration. #### [Responding to mandate events](/docs/collect-payments/events-and-webhooks/mandate-events) Handle mandate lifecycle events to keep your integration up to date. ## Supporting Mandates Set Up Outside of Your Product URL: https://docs.gocardless.com/docs/partner-integrations/supporting-mandates-set-up-outside-of-your-product > Allow your users to import mandates set up outside your product. # Supporting mandates set up outside of your product To provide the best experience, you should consider allowing your users to "import" mandates set up outside your product so they can bill their customers within your product. There are three reasons why your users might have mandates in this situation: #### Existing GoCardless users Some of your users will have already been using GoCardless before connecting it to your product, and may already have Direct Debit mandates set up with their customers. #### Bulk changes If your user was previously using Direct Debit through another provider, they can "bulk change" their existing mandates from their existing provider to GoCardless (subject to availability). #### Mixed usage Your users might choose to add customers using the GoCardless Dashboard, the API, or another integration to better match their workflow. You can support importing mandates in two main ways: #### Automated imports Fetch a list of the user's mandates using the [Mandates API](/docs/api-reference/mandate), then match customers' personal details (`given_name`, `family_name`, `company_number`, and `email`) against your application's internal records to automatically suggest matches, allowing the user to approve or correct them. #### Manual imports Allow users to export a list of customers from your product as a spreadsheet, fill in the mandate IDs from GoCardless, and then upload the completed spreadsheet or email it back to you so you can update your internal records. > **Tip:** > We recommend automated imports — this makes it as easy as possible for your customers to get set > up and get the best value from your integration, whilst keeping manual administrative work to a > minimum. ## Building automatic mandate matching Automatically loading and matching existing Direct Debit mandates provides the best customer experience, making importing your users' existing customers an easy and integrated part of the process of connecting GoCardless to your product. This guide walks through how to pull those mandates into your platform and allow the merchant to link them to the right customer records, so payments can be collected without requiring your merchants' customers to re-authorise. > **Info: Note** > This flow is triggered at the point of OAuth connection and runs in the background. It should be > invisible to the merchant's end customers. ### Overview The mandate migration process has three phases: #### [1. Data Retrieval](#phase-1-data-retrieval) Fetch the merchant's existing mandates and customers from the GoCardless API. #### [2. Tiered Matching](#phase-2-tiered-matching-logic) Automatically link GoCardless customer records to your platform's user records using a cascading match strategy. #### [3. Review & Finalisation](#phase-3-review-and-finalisation) Present a sync summary to the merchant, allow manual resolution of any unmatched records, and store the resulting `mandate_id` links. ### Phase 1: Data retrieval When a merchant clicks "Sync Existing Mandates" after connecting via OAuth, your platform should immediately fetch their mandates and customers in parallel using their saved access token. See the following Open API reference links for example requests in languages we offer client libraries in, as well as example JSON responses. | Request | Reference | | -------------- | ---------------------------------------------------------------------------------- | | List Mandates | [Open API / Mandate / list_mandate](/docs/api-reference/mandate#list-mandates) | | List Customers | [Open API / Customer / list_customer](/docs/api-reference/customer#list-customers) | Your platform should consolidate these two responses, joining on `mandates[].links.customer = customers[].id`, to build a unified list of mandate-and-customer records ready for matching. ### Phase 2: Tiered matching logic Once the data is retrieved, run automated matching in the background. The matching logic is tiered — each tier is attempted in order, and the first successful match wins. Unresolved records fall through to the next tier. > **Info: Note** > This process runs entirely server-side and should complete before the sync summary is shown to the > merchant. ### Tier 1 — Exact email match Compare `customer.email` (GoCardless) against `user.email` (your platform). This is the highest-confidence match and will resolve the majority of records. Treat any exact email match as confirmed without requiring merchant review. ```json GC customer.email == Platform user.email → Auto-matched ✓ ``` ### Tier 2 — Metadata match > **Warning: Prerequisite** > This tiered approach only works if your customer has input a unique identification number > against their customers on GoCardless. If no email match is found, check whether the GoCardless customer record contains a `partner_id` in its metadata field that corresponds to a user ID in your platform. ```json GC customer.metadata['partner_id'] == Platform user.id → Auto-matched ✓ ``` ### Tier 3 — Fuzzy name and postal code match If neither of the above tiers produces a match, attempt a fuzzy match on the combination of the customer's full name and postal code. ```json GC (given_name + family_name + postal_code) ≈ Platform (name + postal_code) → Probable match, flagged for review ``` Fuzzy matches should be surfaced in the sync summary as "Probable matches" rather than confirmed auto-matches. The merchant should review and confirm these before they are finalised. Records that fail all three tiers are marked "Unresolved" and require manual pairing. ### Phase 3: Review and finalisation Once matching completes, display a sync summary screen to the merchant. This gives them an overview of what was matched automatically and what needs their attention. ### Sync summary Show the merchant a breakdown similar to the following: | Status | Count | Action Required | | ---------------- | ----- | ------------------------------------------------------------------ | | Auto-matched | 85 | The Merchant confirms they are correct and confirms the auto-match | | Probable matches | 6 | The merchant should review and confirm or reassign | | Unresolved | 5 | The merchant must manually pair with a customer record | ### Manual review For any Unresolved or Probable match records, present the merchant with the GoCardless customer details alongside a search or dropdown to select the correct customer from your platform. The merchant should be able to: - Confirm a suggested probable match - Reassign a probable match to a different customer record - Manually pair an unresolved mandate to a customer record - Skip a mandate if it should not be linked (e.g. a lapsed customer no longer in your platform) ### Finalisation Once the merchant has reviewed outstanding records and clicks "Confirm & Link", your platform should: 1. Store the `gc_mandate_id` against the matched customer record in your database. 2. Mark those mandates as available for payment collection. 3. Display a confirmation message to the merchant. After this point, payments can now be collected — mandates are linked and available on the relevant customer profiles. ### Storing the mandate link Once confirmed, persist the relationship between your platform's customer record and the GoCardless mandate ID. At minimum, store: | Field | Description | | ------------------ | --------------------------------------------------------- | | `platform_user_id` | Your internal customer identifier | | `gc_mandate_id` | The GoCardless mandate ID (e.g. MD123ABC) | | `gc_customer_id` | The GoCardless customer ID (e.g. CU123ABC) | | `match_method` | How the match was made: email, metadata, fuzzy, or manual | | `linked_at` | Timestamp of when the link was confirmed | You can then use the stored `gc_mandate_id` in subsequent payment creation calls on behalf of the merchant. ### Error handling | Scenario | Recommendation | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | API rate limit hit during retrieval | Implement exponential backoff and retry. See [rate limiting](/docs/api-reference/limits#rate-limiting). | | Mandate status is not active | Exclude cancelled, expired, and failed mandates from the sync. Only surface `active` and `pending_submission` mandates. | | Merchant has no existing mandates | Show an empty state — do not surface the manual pairing UI. | | OAuth token missing or expired | Redirect the merchant to reconnect via OAuth before proceeding. See [Connect your merchants](/docs/partner-integrations/connect-your-merchants). | ## What's Next? #### [Set up mandates](/docs/partner-integrations/setting-up-mandates) Create Direct Debit mandates on behalf of your merchant's customers. #### [Webhooks for partners](/docs/partner-integrations/webhooks-for-partners) Listen for real-time events on mandates, payments, and billing requests. ## UX Guides & Resources URL: https://docs.gocardless.com/docs/partner-integrations/ux-guides-and-resources > Best practices for user experience in your GoCardless partner integration. # User Experience Guide This guide is intended to help you build the best experience for your users. We've imagined a simple invoicing application (called 'Acme') to help illustrate the recommendations. The sections below serve as a checklist for things you should consider when integrating with GoCardless. #### [1. General recommendations](#general-recommendations) High-level principles that apply throughout the integration. #### [2. Discovering GoCardless](#discovering-gocardless-while-using-your-product) Where and how to surface GoCardless within your product. #### [3. Setting up the integration](#setting-up-the-gocardless-integration) Making the OAuth connection flow seamless for merchants. #### [4. Verifying in GoCardless](#verifying-in-gocardless) Prompting merchants to verify before they can receive payouts. #### [5. Requesting a Direct Debit mandate](#requesting-a-customer-to-set-up-a-direct-debit) How to ask customers to set up a mandate across different touchpoints. #### [6. Collecting a payment](#collecting-a-payment) Surfacing payment collection at the right moment in your UI. #### [7. Automating payments](#automating-payments-and-direct-debit-requests) Encouraging merchants to automate to improve cash flow. #### [8. Displaying error states](#clearly-displaying-error-states) Helping merchants act when mandates fail or payments are rejected. ## General recommendations Before we look at the different steps in the user journey, here are some high-level principles that apply throughout: #### Keep key actions in your product Frequent actions like taking payments and managing mandates should live in your interface. Less frequent tasks like settings and help can live in GoCardless. #### Provide help resources Give users a way to get in touch and link to relevant GoCardless resources at each step of the journey — especially during onboarding. #### Use clear, concise language Let users know where they are and what is happening at every step of the flow. ## Discovering GoCardless while using your product The first thing to consider is how to let your users know that they can use a GoCardless integration with your product. When you do that, provide a clear way for them to add the integration, explain the value of GoCardless in a clear and concise way, and focus on our main benefits: - GoCardless is made for recurring payments. - GoCardless allows you to collect invoice payments and subscriptions. - GoCardless allows you to split payments into multiple instalments and collect payments in different currencies (if you support these features). Display this information at steps of the journey where it will be relevant to them. These steps tend to be the following for the majority of our partners: ### During onboarding Encourage them to add a payment method while they're getting started with your product: ![02-onboarding-add-method](/images/docs/partner-integrations/ux-guides-and-resources/02-onboarding-add-method.jpeg) ### While adding a new customer Encourage them to set up a payment method when they are adding a new customer: ![03-new-customer-add-method](/images/docs/partner-integrations/ux-guides-and-resources/03-new-customer-add-method.jpeg) ### When sending an invoice Bring GoCardless to their attention when they are thinking about invoicing their customer. ![04-new-invoice-add-method](/images/docs/partner-integrations/ux-guides-and-resources/04-new-invoice-add-method.jpeg) ### On your settings page If you offer a way to add a payment method from your settings page, make them aware that they can also add GoCardless now. ![05-payment-settings-add-method](/images/docs/partner-integrations/ux-guides-and-resources/05-payment-settings-add-method.jpeg) ## Setting up the GoCardless integration Make the setup process as seamless as possible — connecting your product and GoCardless should require as few steps as possible. At this point, you should **explain clearly what is happening and reassure your users**. ![06-connect](/images/docs/partner-integrations/ux-guides-and-resources/06-connect.jpeg) ## Verifying in GoCardless Once the integration is set up, your user might need to verify their GoCardless account. You can check whether this is [required through the API](/docs/partner-integrations/getting-your-users-verified), and direct the user to our onboarding flow if needed. Ask them to verify in a way that is noticeable and feels important — **they won't receive payouts if they don't**. ![07-dashboard-verify-reminder](/images/docs/partner-integrations/ux-guides-and-resources/07-dashboard-verify-reminder.jpeg) ## Requesting a customer to set up a Direct Debit ### During customer onboarding The next step for your user is to request a customer to complete a Direct Debit mandate so they can take payments from them. **You should do this when they are onboarding a new customer**, as that is the step where the user and their customer are thinking about payment settings. ![08-new-customer-method-added](/images/docs/partner-integrations/ux-guides-and-resources/08-new-customer-method-added.jpeg) ### Bulk requests Allow your users to **make multiple mandate requests in bulk** to save time when onboarding multiple customers at once. ![09-customers-bulk-actions](/images/docs/partner-integrations/ux-guides-and-resources/09-customers-bulk-actions.jpeg) ### Shareable mandate links You can also **provide a mandate setup link in your product that your merchants can copy** and use wherever they like, for example in emails or on their website. See [setting up Direct Debit mandates](/docs/partner-integrations/setting-up-mandates) for how to implement this. ![17-generic-link](/images/docs/partner-integrations/ux-guides-and-resources/17-generic-link.jpeg) You can also let your users know about the ability to **import existing mandates** they may have already set up using the GoCardless dashboard or via another integration. ![18-mandate-import](/images/docs/partner-integrations/ux-guides-and-resources/18-mandate-import.jpeg) ### Email notifications Your users will want to know what their customers will see and have control over what is sent to them. If your integration sends emails to customers requesting a mandate, offer a **preview of the email and the option to edit the copy**. See [handling customer notifications](/docs/tutorials/handling-customer-notifications) for how to implement this. ![10-email-template](/images/docs/partner-integrations/ux-guides-and-resources/10-email-template.jpeg) ### On invoices **Invoices and subscription pages** are another natural touchpoint where merchants think about payment settings. Encourage them to request a mandate here too. ![11-new-invoice-dd-not-setup](/images/docs/partner-integrations/ux-guides-and-resources/11-new-invoice-dd-not-setup.jpeg) If you allow mandate requests when sending an invoice, surface it as a **"Pay with Direct Debit"** button on the invoice itself. ![12-invoice-preview-dd-not-setup](/images/docs/partner-integrations/ux-guides-and-resources/12-invoice-preview-dd-not-setup.jpeg) ### Confirmation screen Consider designing a confirmation screen for customers to land on after completing a mandate. Show a **clear message confirming the Direct Debit is set up and what happens next**. ![19-dd-confirmation](/images/docs/partner-integrations/ux-guides-and-resources/19-dd-confirmation.jpeg) ### Displaying mandate status Your users will want to see which customers have a Direct Debit set up and which ones they need to follow up with. Display the [Direct Debit status](/docs/api-reference/mandate) clearly on both the customer list and the individual customer page. ![20-customer-status](/images/docs/partner-integrations/ux-guides-and-resources/20-customer-status.jpeg) ![13-customer-page](/images/docs/partner-integrations/ux-guides-and-resources/13-customer-page.jpeg) ## Collecting a payment Once a Direct Debit mandate has been set up, your user can collect payments. The most common moment is when creating an invoice or subscription, so surface that option there. **Explain clearly what options are available and how the payment process works**. ![14-new-invoice-dd-setup](/images/docs/partner-integrations/ux-guides-and-resources/14-new-invoice-dd-setup.jpeg) Your users need to see the [status of every payment](/docs/api-reference/payment). Display it clearly on an overview page like an invoices list as well as the individual invoice or subscription page. ![15-invoices](/images/docs/partner-integrations/ux-guides-and-resources/15-invoices.jpeg) ![16-new-invoice-paid](/images/docs/partner-integrations/ux-guides-and-resources/16-new-invoice-paid.jpeg) If payments aren't collected automatically, **allow users to choose when to collect — as soon as possible or at a later date**. Make sure your implementation creates the payment early enough to hit the date the merchant needs. ![21-manual-collection-scheduled](/images/docs/partner-integrations/ux-guides-and-resources/21-manual-collection-scheduled.jpeg) ## Automating payments and Direct Debit requests Automation helps your users improve cash flow and reduces admin time. **Once your user has collected their first payment, encourage them to automate collections and mandate requests.** Lead with cash flow when prompting automation on invoices or subscriptions. ![22-new-invoice-dd-setup-callout](/images/docs/partner-integrations/ux-guides-and-resources/22-new-invoice-dd-setup-callout.jpeg) Lead with reduced admin when prompting automation of Direct Debit requests, and surface it at the right moment — for example, when adding a new customer. ![23-new-customer-method-added-callout](/images/docs/partner-integrations/ux-guides-and-resources/23-new-customer-method-added-callout.jpeg) If you support [automatically retrying payments](/docs/optimise/reduced-failed-payments-with-success-plus), draw your users' attention to it once it's relevant to them. ![26-retry-automation](/images/docs/partner-integrations/ux-guides-and-resources/26-retry-automation.jpeg) ## Clearly displaying error states When things go wrong, **alert your users and help them understand the best action to take**. If a mandate has failed, been cancelled, or expired, notify your user and encourage them to contact their customer. ![24-customers-failed](/images/docs/partner-integrations/ux-guides-and-resources/24-customers-failed.jpeg) For payment failures: - Highlight failed payments and clearly display the reason for the failure. - Ensure invoices are not marked as paid, and make it as easy as possible to retry. - Provide a way to resend a mandate request when a payment has failed due to a mandate issue. ![25-invoices-failed](/images/docs/partner-integrations/ux-guides-and-resources/25-invoices-failed.jpeg) ## What's Next? #### [Integration guide](/docs/partner-integrations/integration-guide) Work through the best-practices checklist to ensure a production-ready integration. #### [Go-live checklist](/docs/partner-integrations/go-live-checklist) Complete the self-assessment review before going live. ## Webhooks for Partners URL: https://docs.gocardless.com/docs/partner-integrations/webhooks-for-partners > Receive webhook notifications for your partner integration. # Webhooks for partners A webhook is a real-time request that GoCardless sends to your server to alert you of an event. Adding support for webhooks allows you to receive real-time notifications from GoCardless when events happen in your account, so you can take automated actions. **This is the suggested monitoring approach.** A webhook can contain multiple events, and each has: - a **resource_type**, telling us what kind of resource the event is for, for example, "payments" or "mandates" - an **action**, telling us what happened to the resource, for example, the "failed" action for a payment - **details**, specifying why the event happened ```json { "events": { "id": "EV123", "created_at": "2014-04-08T17:01::06.000Z", "resource_type": "payments", "action": "failed", "details": { "origin": "bank", "cause": "insufficient_funds", "description": "The customer's account had insufficient funds to make this payment.", "scheme": "sepa_core", "reason_code": "AM04", "will_attempt_retry": false }, "metadata": {}, "links": { "payment": "PM123" } } } ``` > **Info: Stay up to date with webhooks** > Read more about how to create a secure webhook handler in the [staying up-to-date with > webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) section. ## Key Webhook Events ### Billing Request Webhooks | **Event** | **Description** | **Suggested Handling** | | --------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | | `flow_visited` | The billing request flow has been visited | Use to detect payer inactivity and expire the billing request if needed | | `flow_exited` | The payer exited the flow without completing it | Consider triggering a push notification for mobile experiences | | `bank_authorisation_denied` | A bank authorisation was denied by the payer | Display the denial reason from `details.description` | | `bank_authorisation_failed` | A bank authorisation failed due to a bank account mismatch | Display the failure reason from `details.description` | | `fulfilled` | The billing request was fulfilled and the mandate and/or payment have been created | Save the mandate and/or payment ID to your database | ![billing-request-state-diagram](/images/docs/partner-integrations/webhooks-for-partners/billing-request-state-diagram.png) See the full list of [billing request webhooks](/docs/api-reference/events/billing-request) in the API reference. ### Mandate Webhooks | **Event** | **Description** | **Suggested Handling** | | ------------------------ | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | | `created` | The mandate has been created | Save the mandate ID to your database | | `submitted` | The mandate has been submitted to the banks | Update the mandate status in your billing system | | `active` | The mandate has been successfully set up by the customer's bank | Update the mandate status in your billing system | | `failed` | The mandate could not be set up — the bank account does not accept Direct Debit or is closed | Update status; allow the customer to use another payment method or re-attempt with a new account | | `cancelled` | The mandate was cancelled by the customer, via the API, or automatically when their account was closed | Update status; request a new payment method and cancel any associated subscriptions | | `expired` | No collections were made within the dormancy period and the mandate has expired | Update status; use the [reinstate endpoint](/docs/api-reference/responses-and-errors#invalid-state) or create a new mandate | | `resubmission_requested` | A reinstate request was made via the mandate reinstate endpoint | Update the mandate status in your billing system | | `reinstated` | The mandate has become active again after being cancelled or expired | Update the mandate status in your billing system | | `replaced` | The mandate was cancelled and replaced by a new one. The event includes `links.new_mandate` | Update the stored mandate ID to the value in `links.new_mandate` | | `blocked` | The mandate matched fraud information or a block list and cannot be unblocked | Update status; cancel any subscriptions against this mandate | ![mandate-state-diagram](/images/docs/partner-integrations/webhooks-for-partners/mandate-state-diagram.png) See the full list of [mandate webhooks](/docs/api-reference/events/mandate) in the API reference. ### Payment Webhooks | **Event** | **Description** | **Suggested Handling** | | ------------------------ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------ | | `created` | The payment has been created | Save the payment ID to your database | | `submitted` | The payment has been submitted to the banks | Update the payment status in your billing system | | `confirmed` | The payment has been collected and is held by GoCardless before payout | Update the payment and invoice status | | `paid_out` | The payment has been sent to the creditor's bank account | Update the payment and invoice status | | `failed` | The payment could not be collected. If `will_attempt_retry` is true, Success+ will retry automatically | Update the payment and invoice status | | `cancelled` | The payment was cancelled | Update the payment and invoice status | | `resubmission_requested` | Success+ has scheduled an automatic retry (see `failed`) | Update the payment and invoice status | | `charged_back` | The customer reclaimed the payment via the Direct Debit Guarantee | Update the payment and invoice status | | `chargeback_cancelled` | The customer's bank cancelled the chargeback request | Update the payment and invoice status | ![payment-state-diagram](/images/docs/partner-integrations/webhooks-for-partners/payment-state-diagram.png) See the full list of [payment webhooks](/docs/api-reference/events/payment) in the API reference. ### Refund Webhooks | **Event** | **Description** | **Suggested Handling** | | --------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | | `created` | A refund has been created (`details.cause`: `payment_refunded`, `details.origin`: `api`) | Update the refund status and expose it to your merchants | | `failed` | The refund did not reach the customer; funds are returned to you (`details.cause`: `refund_failed`) | Update the refund status and expose it to your merchants | | `paid` | The refund has been paid to the customer (`details.cause`: `refund_paid`) | Update the refund status and expose it to your merchants | See the full list of [refund webhooks](/docs/api-reference/events/refund) in the API reference. > **Tip: Retry failed webhooks from the Partner Dashboard** > If a webhook fails to deliver, you can view its status and retry it directly from the [Partner > Dashboard](https://manage.gocardless.com/). Navigate to a merchant, payments tab, click on the > payment, and you'll find the webhook status and retry option there. ## What's Next? #### [Stay up to date with webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) Learn how to create a secure webhook endpoint and verify webhook signatures. #### [Go-live checklist](/docs/partner-integrations/go-live-checklist) Complete the self-assessment review and submit your integration for approval. --- # API Reference ## Anatomy URL: https://docs.gocardless.com/docs/api-reference/anatomy > Flows, state diagrams, and timing information for mandates and payments. # Anatomy The following state diagrams explain the flows of mandate setup and payment creation. There's also a short section on how timings work per scheme. ## Mandate setup ![Mandate setup flow](/images/api-reference/mandate-setup@2x-rebrand.png) ## Payment creation ![Payment creation flow](/images/api-reference/payment-creation@2x-rebrand.png) ## Timing by scheme Direct Debit payments don't process instantly and work differently from card payments. Timings vary by scheme — expand the relevant one below. > **Tip:** > You can still test all schemes as if they were instant. See [Scenario > Simulators](/docs/developer-resources/scenario-simulators) for details. ### Bacs (UK) - **Mandate already in place:** collected 2 working days after submission, 95% confirmed after 3 working days, 100% confirmed after 4 working days. - **Mandate also needs to be created:** add 2 working days to each of the above. Customers must be notified at least **3 working days** before payment leaves their account. [Detailed UK timings →](https://gocardless.com/direct-debit/timings/) ### ACH (US) - Standard ACH: **4–5 business days**. - Faster ACH via GoCardless: **2–3 business days**. [Detailed ACH timings →](https://support.gocardless.com/hc/en-gb/articles/360023784433-ACH-US-payment-timings) ### Autogiro (Sweden) - New mandates take up to **6 interbank business days** before payments can be submitted under them. - Submit all payment collections **2 interbank business days** before the payment due date. Customers must be notified at least **8 working days** in advance. [Detailed Autogiro timings →](https://gocardless.com/guides/bg-autogiro/introduction) ### BECS (Australia) - Submit all payment collections **1 interbank business day** before the payment due date. [Detailed BECS timings →](https://gocardless.com/guides/becs-direct-debit/timings/) ### BECS NZ (New Zealand) - Submit all payment collections **2 interbank business days** before the payment due date. [Detailed BECS NZ timings →](https://gocardless.com/guides/becs-nz/timings/) ### Betalingsservice (Denmark) - New mandates must be created at least **1 working day** before payments can be created. - Submit collections **8 working days before the end of the month** preceding the target payment month. [Detailed Betalingsservice timings →](https://gocardless.com/guides/betalingsservice/betalingsservice-timings/) ### PAD (Canada) - Submit all payment collections **3 interbank business days** before the payment due date. [Detailed PAD timings →](https://gocardless.com/guides/pad/timings/) ### PayTo (Australia) No advance notice period. Payments can be taken **almost instantaneously**. ### Faster Payments (UK) No advance notice period. Payments can be taken **almost instantaneously**. ### SEPA Core (Europe) - Submit all payment collections **1 interbank business day** before the payment due date. - Notify customers **2 working days** in advance, or as soon as the payment is created if it's within 2 days of collection. [Detailed SEPA timings →](https://gocardless.com/guides/sepa/timings/) ## What's next #### [Making Requests](/docs/api-reference/making-requests) Authentication, versioning, and how to structure every API call. #### [Responses and Errors](/docs/api-reference/responses-and-errors) HTTP response codes and how to handle each error type. ## Backwards Compatibility URL: https://docs.gocardless.com/docs/api-reference/backwards-compatibility > What changes GoCardless considers backwards compatible in the API. # Backwards Compatibility > **Info:** > GoCardless may add new fields to API responses at any time. Make sure your integration handles > unknown fields gracefully — for example, by ignoring properties you do not recognise rather than > treating them as errors. The following changes are considered backwards compatible and may be made at any time without advance notice: - Adding new API endpoints - Adding new properties to responses from existing endpoints - Reordering properties returned from existing endpoints - Adding optional request parameters to existing endpoints - Altering the format or length of IDs (strings will never exceed 255 characters) - Altering `message` attributes returned by validation failures or other errors - The number of and duration between retries for failed webhooks - The behaviour of Scenario Simulators - Sending webhooks for new event types Any changes that are not backwards compatible will be released as a new API version and communicated in advance. ## What's next #### [Changelog](/docs/api-reference/changelog) Review the full history of changes to the GoCardless API. #### [Making Requests](/docs/api-reference/making-requests) Learn how to authenticate and structure API requests. ## Certificate Policy URL: https://docs.gocardless.com/docs/api-reference/certificate-policy > GoCardless TLS certificate policy and guidance on certificate pinning. # Certificate Policy GoCardless enforces HTTPS for all API communications using TLS. Certificates are currently provided by **Google Trust Services (GTS Root R1 CA)**. ## Verifying the Certificate You can verify the current certificate being served by GoCardless using the `openssl` command: ```bash openssl s_client -connect api.gocardless.com:443 -showcerts ``` This will output the certificate chain, including the root CA. > **Warning:** > **Do not implement certificate pinning** in your integration. GoCardless reserves the right to > change its certificate authority (CA) or certificate at any time. If you pin the current > certificate or CA, your integration will break when GoCardless updates its certificates. > GoCardless will provide at least **2 weeks' advance notice** on the [GoCardless status > page](https://www.gocardless-status.com) before making changes to its certificate configuration. ## Change Notification Any changes to the certificate configuration — including changes to the CA provider — will be announced on the [GoCardless status page](https://www.gocardless-status.com) with at least 2 weeks' notice. Subscribe to the status page to receive notifications. ## What's next #### [Security Requirements](/docs/api-reference/security-requirements) Review the security requirements for accessing bank account details. #### [Making Requests](/docs/api-reference/making-requests) Learn how to authenticate and structure API requests to GoCardless. ## Character Sets URL: https://docs.gocardless.com/docs/api-reference/character-sets > Allowed characters and maximum lengths for payment and mandate references by scheme. # Character Sets Different schemes allow different character sets for payment and mandate references. All schemes allow alphanumeric characters (A-Z and 0-9). Some allow additional special characters. Any references containing disallowed characters will return an error that includes the offending characters. GoCardless formats references to match each bank and scheme as accurately as possible. ## Allowed Characters by Scheme | Scheme | Allowed Characters | Max Length | | -------------------- | ---------------------------------------------------- | ---------------------------------------------- | | **Bacs** | A-Z, 0-9, space, `/` `-` `.` `&` | 18 chars (payment ref), 10 chars (mandate ref) | | **SEPA Core** | A-Z, 0-9, space, `/` `-` `?` `:` `(` `)` `.` `,` `+` | 35 chars | | **ACH** | A-Z, 0-9, space, `-` | 10 chars | | **Autogiro** | A-Z, 0-9 | 11 chars | | **Betalingsservice** | A-Z, 0-9, `-` | 20 chars | | **BECS (AU)** | A-Z, 0-9, space, `-` `.` | 18 chars | | **BECS NZ** | A-Z, 0-9, space, `-` | 12 chars | | **PAD** | A-Z, 0-9, space, `-` | 10 chars | | **PayTo** | A-Z, 0-9, space | 280 chars | ## What's next #### [Supported Schemes](/docs/api-reference/schemes) View all direct debit and alternative payment schemes supported by GoCardless. #### [Backwards Compatibility](/docs/api-reference/backwards-compatibility) Learn what changes are considered backwards compatible in the GoCardless API. ## Compliance Requirements URL: https://docs.gocardless.com/docs/api-reference/compliance-requirements > Compliance requirements for GoCardless payment pages and customer notifications by scheme. # Compliance Requirements When collecting payments through GoCardless, you must meet certain compliance requirements depending on the scheme you are using. These requirements cover payment page content and customer notifications. > **Info:** > If you use GoCardless-hosted payment pages, most compliance requirements are handled for you > automatically. Using hosted pages is the easiest way to stay compliant. ## Payment Page Requirements Each scheme has specific requirements for the content and format of payment pages shown to customers. Review the requirements for the schemes you use: #### [ACH (Standard)](https://support.gocardless.com/hc/en-us/articles/18121148374044-United-States-ACH-payment-page-requirements) Payment page requirements for the US ACH scheme (standard). #### [ACH (Advanced)](https://support.gocardless.com/hc/en-us/articles/18121148374044-United-States-ACH-payment-page-requirements) Payment page requirements for the US ACH scheme (advanced). #### [Autogiro](https://support.gocardless.com/hc/en-us/articles/360001245865-Sweden-Autogiro-custom-payment-pages) Payment page requirements for the Swedish Autogiro scheme. #### [Bacs](https://support.gocardless.com/hc/en-us/articles/360001245325-United-Kingdom-Bacs-custom-payment-pages) Payment page requirements for the UK Bacs scheme. #### [BECS](https://support.gocardless.com/hc/en-us/articles/360001246025-Australia-BECS-custom-payment-pages) Payment page requirements for the Australian BECS scheme. #### [BECS NZ](https://support.gocardless.com/hc/en-us/articles/360001449985-New-Zealand-BECS-NZ-custom-payment-pages) Payment page requirements for the New Zealand BECS NZ scheme. #### [PAD](https://support.gocardless.com/hc/en-us/articles/360013059874-Canada-PAD-custom-payment-pages) Payment page requirements for the Canadian PAD scheme. #### [SEPA Core](https://support.gocardless.com/hc/en-us/articles/360001245585-Eurozone-SEPA-custom-payment-pages) Payment page requirements for the SEPA Core scheme. ## Customer Notification Requirements You must notify customers before collecting payments under most schemes. Review the notification requirements for the schemes you use: #### [ACH Notifications](https://support.gocardless.com/hc/en-us/articles/360023787373-United-States-ACH-custom-notifications) Customer notification requirements for the US ACH scheme. #### [Autogiro Notifications](https://support.gocardless.com/hc/en-us/articles/360001244109-Sweden-Autogiro-custom-notifications) Customer notification requirements for the Swedish Autogiro scheme. #### [Bacs Notifications](https://support.gocardless.com/hc/en-us/articles/360001245445-United-Kingdom-Bacs-custom-notifications) Customer notification requirements for the UK Bacs scheme. #### [BECS Notifications](https://support.gocardless.com/hc/en-us/articles/360001244249-Australia-BECS-custom-notifications) Customer notification requirements for the Australian BECS scheme. #### [BECS NZ Notifications](https://support.gocardless.com/hc/en-us/articles/360001450825-New-Zealand-BECS-NZ-custom-notifications) Customer notification requirements for the New Zealand BECS NZ scheme. #### [PAD Notifications](https://support.gocardless.com/hc/en-us/articles/360013070374-Canada-PAD-custom-notifications) Customer notification requirements for the Canadian PAD scheme. #### [SEPA Notifications](https://support.gocardless.com/hc/en-us/articles/360001245785-Eurozone-SEPA-custom-notifications) Customer notification requirements for the SEPA Core scheme. ## What's next #### [Restrictions](/docs/api-reference/restrictions) Learn about the restrictions and limitations that apply to the GoCardless API. #### [Anatomy of a GoCardless Integration](/docs/api-reference/anatomy) Understand the building blocks of a GoCardless integration. ## Data Conventions URL: https://docs.gocardless.com/docs/api-reference/data-conventions > Date formats, pagination, and data conventions used across the GoCardless API. # Data Conventions ## Dates and times All timestamps are ISO 8601 with timezone information, for example `2014-02-27T15:05:06.123Z`. Endpoints that accept a date (not a datetime) expect the format `YYYY-MM-DD`, for example `2014-02-27`. ## Cursor pagination All list endpoints are ordered and paginated reverse-chronologically by default. ### Request parameters | Parameter | Description | | --------- | ---------------------------------------------------------------------- | | `before` | ID of the object immediately following the array to be returned. | | `after` | ID of the object immediately preceding the array to be returned. | | `limit` | Maximum number of objects to return. Default `50`, max `500`, min `1`. | ### Response metadata Every paginated response includes a `meta.cursors` object: | Field | Description | | -------- | ----------------------------------------------------------------------- | | `before` | ID of the first resource returned. | | `after` | ID of the last resource returned. | | `limit` | Upper bound applied. May be less than requested if fewer objects exist. | ### Example ```http GET https://api.gocardless.com/payments?after=ID789 HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json { "payments": [ { "id": "PM0001", "amount": 1000, "currency": "GBP" }, { "id": "PM0002", "amount": 2000, "currency": "GBP" } ], "meta": { "cursors": { "before": "PM0001", "after": "PM0002" }, "limit": 50 } } ``` > **Tip:** > To page through all results, keep passing the `after` cursor from each response until the array is > empty or shorter than the requested `limit`. ## What's next #### [Responses and Errors](/docs/api-reference/responses-and-errors) HTTP response codes and how to handle each error type. #### [Making Requests](/docs/api-reference/making-requests) Authentication, headers, and how to structure every API call. ## IP Addresses URL: https://docs.gocardless.com/docs/api-reference/ip-addresses > Guidance on IP address allowlisting for GoCardless API and webhook traffic. # IP Addresses ## API traffic Adding GoCardless IPv4 addresses to an allowlist is **not a supported approach** for securing API traffic. Our IP addresses may change as part of normal operations and must not be relied upon to remain static. This is consistent with best practices for highly-available services. We recommend relying on the stronger security provided by **Transport Layer Security (TLS)**, which validates GoCardless's identity as part of the normal certificate chain check. Certificate revocation should also be checked for all parts of the chain. For help implementing this, contact [api@gocardless.com](mailto:api@gocardless.com). ## Webhook traffic Allowlisting IP addresses for **inbound webhook traffic** is a valid practice. GoCardless publishes the static IP addresses used to send webhooks, and provides at least two weeks' advance notice before any changes. See the [Webhooks Reference — IP Addresses](/docs/api-reference/webhooks#ip-addresses) section for the current list. ## What's next #### [Webhooks Reference](/docs/api-reference/webhooks) Delivery guarantees, signing, retries, and the full IP address list. #### [Security Requirements](/docs/api-reference/security-requirements) TLS and other security requirements for GoCardless integrations. ## Limits and Safeguards URL: https://docs.gocardless.com/docs/api-reference/limits > Rate limiting, timeouts, and idempotency keys for the GoCardless API. # Limits and Safeguards ## Rate limiting A rate limit applies to all API requests to prevent excessive load from any single integrator. | Context | Limit | | ------------------- | ------------------------------------ | | Standard | 1,600 requests / minute | | Partner integration | 1,600 requests / minute per merchant | If you exceed the limit, the API returns a `429` status with a `rate_limit_exceeded` error. These requests are safe to retry. Check the response headers to know when you can resume: ```http ratelimit-limit: 1000 ratelimit-remaining: 163 ratelimit-reset: Thu, 03 May 2018 16:00:00 GMT ``` > **Info:** > If you're making a large batch of requests, think of 1,000 requests/minute as a performance target > — hitting it means completing the task as fast as possible. ## Timeouts | Type | Duration | Notes | | ----------------- | ---------- | ------------------------------------------------------------------- | | Request timeout | 29 seconds | A single request cannot exceed this duration. | | Keepalive timeout | 10 minutes | Persistent connections with no requests for this period are closed. | ## Idempotency keys Some requests are dangerous to retry without protection. When creating resources, pass an `Idempotency-Key` header to ensure the key can only be used for one successful request: ```http Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890 ``` If a resource already exists for that key, the API returns a `409 idempotent_creation_conflict` error with a `links.conflicting_resource_id` pointing to the existing resource. > **Warning: Double-charge risk** > Always use idempotency keys when creating payments or mandates. A network timeout that causes you > to retry without one can result in the same payment being taken twice. **Guidelines:** - Keys must be no longer than 128 characters - Use UUIDv4 — any non-repeating unique identifier is sufficient - Keys are honoured for at least 30 days - Our [API libraries](/docs/developer-resources/client-libraries) generate idempotency keys automatically ## What's next #### [Responses and Errors](/docs/api-reference/responses-and-errors) Understand `429 rate_limit_exceeded` and `409 idempotent_creation_conflict` in context. #### [Data Conventions](/docs/api-reference/data-conventions) Date formats, cursor pagination, and other request conventions. ## Local Bank Details URL: https://docs.gocardless.com/docs/api-reference/local-bank-details > Field formats for local bank account details by country. # Local Bank Details When creating customer bank accounts, you can supply either an IBAN or local bank details specific to the country. This page documents the accepted field formats for each country. ### IBAN (General) Most European countries accept IBAN as the primary format. You can optionally supply a `country_code` alongside the IBAN — if provided, it must match the country prefix of the IBAN. The `currency` defaults to the country's primary currency. If you are collecting SEPA payments from a GB IBAN, explicitly pass `currency: "EUR"`. Note: IBANs are **not supported** for AUD (Australia) or SEK (Sweden) — you must use local bank details for those currencies. ```json { "customer_bank_accounts": { "iban": "GB60 BARC 2000 0055 7799 11" } } ``` See individual country entries below for local format alternatives. ### United Kingdom Supply a 6–8 digit `account_number` and a 6 digit `branch_code` (sort code). ```json { "country_code": "GB", "account_number": "55779911", "branch_code": "200000" } ``` The sort code can be supplied with or without hyphens (e.g. `20-00-00` or `200000`). ### Australia Supply a 5–9 digit `account_number` and a 6 digit `branch_code` (BSB number). IBAN is not supported for AUD. ```json { "country_code": "AU", "account_number": "0123456789", "branch_code": "012345" } ``` The BSB number can be supplied with or without a hyphen (e.g. `012-345` or `012345`). ### United States Supply a 9 digit `bank_code` (routing number), an `account_number` of up to 17 digits, and an `account_type` of either `"checking"` or `"savings"`. IBAN is not supported for USD. ```json { "country_code": "US", "account_number": "2715500356", "bank_code": "026073150", "account_type": "checking" } ``` The routing number must be exactly 9 digits. ### Canada Supply a 2–3 digit `bank_code` (Financial Institution Number / FIN), a 5 digit `branch_code` (Branch Transit Number), and a 7–12 digit `account_number`. ```json { "country_code": "CA", "account_number": "1234567", "bank_code": "0003", "branch_code": "00006" } ``` The bank code should be supplied without leading zeros where applicable. ### Sweden Supply a 4–5 digit `branch_code` (clearingnummer) and an `account_number` of up to 10 digits (kontonummer). IBAN is not supported for SEK. ```json { "country_code": "SE", "account_number": "1234512", "branch_code": "5527" } ``` The clearingnummer uniquely identifies the bank branch. ### New Zealand Supply a 2 digit `bank_code`, a 4 digit `branch_code`, and an `account_number` consisting of 7 digits plus a 2–3 digit suffix, concatenated with a hyphen (e.g. `0123456-89`). IBAN is not supported for NZD. ```json { "country_code": "NZ", "account_number": "0123456-89", "branch_code": "0123", "bank_code": "01" } ``` The full New Zealand bank account number format is: `BB-bbbb-AAAAAAA-SSS`. ### Denmark Supply a 2–4 digit `bank_code` (registreringsnummer) and a 9–10 digit `account_number` (kontonummer). Alternatively, you can supply the bank code embedded in the `account_number` field, separated by a hyphen or space. ```json { "country_code": "DK", "account_number": "3179681", "bank_code": "345" } ``` The registreringsnummer identifies the specific bank branch. ### Austria Supply a 4–11 digit `account_number` (Kontonummer) and a 5 digit `bank_code` (Bankleitzahl). IBAN is the more common format for Austria. ```json { "country_code": "AT", "account_number": "234573201", "bank_code": "19043" } ``` Using IBAN is recommended where possible for Austrian accounts. ### Belgium Supply only the `account_number` (Rekeningnummer / Numéro de compte). The first 3 digits of the account number identify the bank. IBAN is also accepted. ```json { "country_code": "BE", "account_number": "539-0075470-34" } ``` The account number can be supplied with or without hyphens. ### France Supply a 5 digit `bank_code` (Code banque), a 5 digit `branch_code` (Code guichet), and an `account_number` of up to 11 digits including 2 check digits (Clé RIB). French overseas departments and territories (DOMs/TOMs) use the same format with their respective ISO country codes: GF, GP, MQ, YT, RE, BL, MF, PM. ```json { "country_code": "FR", "account_number": "123456789 11", "bank_code": "30004", "branch_code": "00001" } ``` Together these form the RIB (Relevé d'Identité Bancaire). ### Germany Supply a 1–10 digit `account_number` (Kontonummer) and an 8 digit `bank_code` (Bankleitzahl). IBAN is also accepted. ```json { "country_code": "DE", "account_number": "532013000", "bank_code": "37040044" } ``` The Bankleitzahl (BLZ) identifies the bank and branch. ### Ireland Supply a 6 digit `branch_code` (sort code) and a 6–8 digit `account_number`. IBAN is also accepted. ```json { "country_code": "IE", "account_number": "29823529", "branch_code": "90-21-27" } ``` The sort code can be supplied with or without hyphens. ### Italy Supply a 5 digit `bank_code` (Codice ABI), a 5 digit `branch_code` (CAB), and an `account_number` of up to 12 digits. IBAN is preferred for Italy. ```json { "country_code": "IT", "account_number": "123456", "bank_code": "05428", "branch_code": "11101" } ``` Together with the check character and country code, these form the BBAN component of the Italian IBAN. ### Netherlands Supply a 4 character `bank_code` and an `account_number` (Rekeningnummer) of up to 10 digits. Most Dutch customers will know their IBAN rather than local details. ```json { "country_code": "NL", "account_number": "0417164300", "bank_code": "ABNA" } ``` Using IBAN is recommended for Dutch accounts. ### Spain Supply a 4 digit `bank_code` (código de entidad), a 4 digit `branch_code` (código de oficina), and a 10 digit `account_number` (número de cuenta with 2 check digits prepended). Alternatively, you can supply all components in the `account_number` field as the Código Cuenta Cliente (CCC). ```json { "country_code": "ES", "account_number": "45 0200051332", "bank_code": "2100", "branch_code": "0418" } ``` The CCC format is: BBBB-OOOO-CC-AAAAAAAAAA (bank + office + check digits + account). ### Estonia Supply an `account_number` of up to 14 digits. Note that IBAN replaced local account details in Estonia in 2014, so most customers will have an IBAN. ```json { "country_code": "EE", "account_number": "221020145685" } ``` Using IBAN is strongly recommended for Estonian accounts. ### Latvia Supply a 4 character `bank_code` and a 13 digit `account_number`. Note that IBAN replaced local account details in Latvia in 2005. ```json { "country_code": "LV", "account_number": "0000435195001", "bank_code": "LACB" } ``` Using IBAN is strongly recommended for Latvian accounts. ### Lithuania Supply a 5 digit `bank_code` and an 11 digit `account_number`. Note that IBAN replaced local account details in Lithuania in 2004. ```json { "country_code": "LT", "account_number": "11101001000", "bank_code": "10000" } ``` Using IBAN is strongly recommended for Lithuanian accounts. ### Slovak Republic Supply a 4 digit `bank_code` (Kód banky) and an `account_number` consisting of an optional prefix (Předčíslí, up to 6 digits) followed by the account number (Číslo účtu, up to 8 digits), concatenated together. The traditional written format is `pppppp-aaaaaaaaaa/bbbb`. ```json { "country_code": "SK", "account_number": "198742637541", "bank_code": "1200" } ``` IBAN is also widely used in Slovakia. ### Slovenia Supply a 5 digit `bank_code` and an `account_number` of up to 10 digits. IBAN is also accepted. ```json { "country_code": "SI", "account_number": "123438", "bank_code": "19100" } ``` Using IBAN is recommended for Slovenian accounts. ### Malta Supply a 5 digit `branch_code` (sort code) and an `account_number` of up to 18 digits. IBAN is also accepted. ```json { "country_code": "MT", "account_number": "9027293051", "branch_code": "44093" } ``` Using IBAN is recommended for Maltese accounts. ### Luxembourg Supply a 3 digit `bank_code` and a 13 digit `account_number`. Note that IBAN replaced local account details in Luxembourg in 2002. ```json { "country_code": "LU", "account_number": "9400644750000", "bank_code": "001" } ``` Using IBAN is strongly recommended for Luxembourg accounts. ### Cyprus Supply a 3 digit `bank_code` (Kodikos Trapezas), an optional 5 digit `branch_code` (Kodikos Katastimatos), and a 7–16 digit `account_number`. Alternatively, you can combine both bank and branch codes into an 8 digit `bank_code`. ```json { "country_code": "CY", "account_number": "1200527600", "bank_code": "002", "branch_code": "00128" } ``` IBAN is also accepted for Cypriot accounts. ### Greece Supply a 3 digit `bank_code`, a 5 digit `branch_code`, and a 16 digit `account_number`. IBAN is also accepted. ```json { "country_code": "GR", "account_number": "0000000012300695", "bank_code": "011", "branch_code": "0125" } ``` Using IBAN is recommended for Greek accounts. ### Portugal Supply a 4 digit `bank_code`, a 4 digit `branch_code`, and an `account_number` consisting of 11 digits plus 2 check digits. IBAN is also accepted. ```json { "country_code": "PT", "account_number": "1234567890154 50", "bank_code": "0002", "branch_code": "0123" } ``` Using IBAN is recommended for Portuguese accounts. ### Monaco Monaco uses the same format as France. Supply a 5 digit `bank_code` (Code banque), a 5 digit `branch_code` (Code guichet), and an `account_number` of up to 11 digits including 2 check digits. ```json { "country_code": "MC", "account_number": "0500013M026 06", "bank_code": "20041", "branch_code": "01005" } ``` IBAN is also accepted for Monegasque accounts. ### San Marino San Marino uses the same format as Italy. Supply a 5 digit `bank_code` (Codice ABI), a 5 digit `branch_code` (CAB), and an `account_number` of up to 12 digits. ```json { "country_code": "SM", "account_number": "123456", "bank_code": "05428", "branch_code": "11101" } ``` IBAN is also accepted for San Marinese accounts. ## What's next #### [Supported Schemes](/docs/api-reference/schemes) Review the direct debit and alternative payment schemes supported by GoCardless. #### [Making Requests](/docs/api-reference/making-requests) Learn how to authenticate and structure API requests to GoCardless. ## Making Requests URL: https://docs.gocardless.com/docs/api-reference/making-requests > How to authenticate, version, and structure requests to the GoCardless API. # Making Requests ## Base URLs | Environment | URL | | ----------- | ------------------------------------- | | Live | `https://api.gocardless.com/` | | Sandbox | `https://api-sandbox.gocardless.com/` | The API is only available over HTTPS. Attempting to access the API over HTTP will return a `tls_required` error. ## Healthcheck Both environments expose a health check endpoint you can use to verify connectivity. It requires no authorisation and is not rate limited — a `200` response means the API is available. - `https://api.gocardless.com/health_check` (live) - `https://api-sandbox.gocardless.com/health_check` (sandbox) ## Authentication After creating an access token in the dashboard, pass it in an `Authorization` header using the [bearer scheme](https://www.rfc-editor.org/rfc/rfc6750#section-2.1): ```http Authorization: Bearer TOP_SECRET_ACCESS_TOKEN ``` > **Warning:** > If you're using the [JavaScript > Flow](/docs/collect-payments/integration-types/javascript-drop-in-flow), use a publishable access > token instead. ## Versions Every request must include a `GoCardless-Version` header specifying a released API version: ```http GoCardless-Version: 2015-07-06 ``` | Version | Notes | | ------------ | ------------------------------------------------------------------------------ | | `2015-07-06` | Current version. Removed helper endpoint (replaced with individual endpoints). | ## Headers ### Content type All requests and responses are JSON-formatted and UTF-8 encoded. Include an `Accept` header on all requests: ```http Accept: application/json ``` For `POST` and `PUT` requests, also include `Content-Type` and `Content-Length`: ```http Content-Type: application/json Content-Length: 3495 ``` You may use either `application/json` or `application/vnd.api+json` for both headers. > **Info:** > A missing or incorrect `Content-Type` on a `POST`/`PUT` returns an `invalid_content_type` error. > Most HTTP clients send `Content-Length` automatically — if missing, you'll get `411 Length > Required`. ## HTTP methods The API supports `GET`, `POST`, `PUT`, and `DELETE`. If your HTTP client or proxy doesn't support `PUT` or `DELETE`, send a `POST` with an override header: ```http X-HTTP-Method-Override: PUT X-HTTP-Method-Override: DELETE ``` > **Warning:** > `PATCH` is not supported and will return a `method_not_allowed` error. Use `PUT` to update > existing resources. ## Optional properties When making requests, omit optional properties from the JSON body entirely rather than sending `null`. Our [API libraries](/docs/developer-resources/client-libraries) handle this automatically — it's only relevant if you're constructing raw requests. ## What's next #### [Limits and Safeguards](/docs/api-reference/limits) Rate limiting, timeouts, and idempotency keys. #### [Data Conventions](/docs/api-reference/data-conventions) Date formats and cursor pagination patterns. ## OAuth Reference URL: https://docs.gocardless.com/docs/api-reference/oauth-reference > Complete technical reference for the GoCardless OAuth 2.0 API — endpoints, parameters, error codes, app fees, and webhooks. # OAuth Reference OAuth allows you to act on behalf of other GoCardless accounts. Once a user connects their account to your app, you can use the GoCardless API on their behalf and receive their webhooks. The GoCardless OAuth API conforms to the [OAuth 2.0 spec](https://www.rfc-editor.org/rfc/rfc6749) and works with standard OAuth client libraries available in most languages. For a step-by-step integration walkthrough see [Connect Your Merchants](/docs/partner-integrations/connect-your-merchants). ## Base URLs | Environment | Base URL | | ----------- | ---------------------------------------- | | Live | `https://connect.gocardless.com` | | Sandbox | `https://connect-sandbox.gocardless.com` | ## The OAuth flow 1. Send the user to `GET /oauth/authorize` with your `client_id`, requested `scope`, and `redirect_uri`. 2. The user logs in (or signs up) to GoCardless and agrees to connect their account. 3. GoCardless redirects to your `redirect_uri` with a short-lived `code`. 4. Exchange the `code` for a permanent `access_token` via `POST /oauth/access_token`. 5. Use the `access_token` to make API requests on the user's behalf and receive their webhooks. ## Creating an app Create your app from the [developer section of your GoCardless dashboard](https://manage.gocardless.com/developers). You will be issued a `client_id` and `client_secret` (each 64 characters) which identify your integration. ## GET /oauth/authorize Redirect your user to this endpoint to start the OAuth flow. Use a `GET` request. ```http GET https://connect.gocardless.com/oauth/authorize? response_type=code& client_id=sx6WHUAVMUrinkJNJn8DotVFm& scope=read_write& redirect_uri=https%3A%2F%2Fexample.com%2Fcallback& state=q8wEr9yMohTP& prefill[email]=tim%40acme.com& prefill[given_name]=Tim& prefill[family_name]=Rogers& prefill[organisation_name]=Acme%20Ltd& prefill[country_code]=GB ``` ### Parameters | Parameter | Required | Description | | ---------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `response_type` | Yes | Must be `code`. | | `client_id` | Yes | Your app's `client_id`. | | `scope` | Yes | `read_write` or `read_only`. | | `redirect_uri` | Yes | Must exactly match one of the `redirect_uris` registered on your app. Used for both success and error redirects. | | `state` | No | An arbitrary string returned to you unchanged in the redirect. Use it for a [CSRF token](https://en.wikipedia.org/wiki/Cross-site_request_forgery). Note: can be tampered with by the user, so do not trust implicitly. | | `prefill[email]` | No | Pre-fills the user's email on the login/signup form. | | `prefill[given_name]` | No | Pre-fills the user's first name on the signup form. | | `prefill[family_name]` | No | Pre-fills the user's last name on the signup form. | | `prefill[organisation_name]` | No | Pre-fills the organisation name on the signup form. | | `prefill[country_code]` | No | Pre-fills the organisation country in [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format. | | `language` | No | Language for the login/signup form in [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. Falls back to the most appropriate language if unsupported. | | `initial_view` | No | `signup` or `login`. Defaults to `login` for `read_only` scope and `signup` for `read_write`. | ## Handling the redirect On success, GoCardless redirects to your `redirect_uri` with a `code` (and `state` if you provided one). Exchange the `code` within 5 minutes. ``` GET https://example.com/callback?code=6NJiqXzT7HcgEGsAZXUmaBfB&state=q8wEr9yMohTP ``` ### Redirect errors If the user denies the request, or an error occurs, GoCardless redirects to your `redirect_uri` with `error` and `error_description` parameters. ``` GET https://example.com/callback?error=access_denied&error_description=The%20user%20cancelled%20the%20authorisation%20process. ``` | Error | Description | | --------------------------- | -------------------------------------------------------- | | `access_denied` | The user chose not to connect their account to your app. | | `invalid_request` | `scope` or `response_type` was not provided. | | `invalid_scope` | `scope` was not `read_only` or `read_write`. | | `unsupported_response_type` | `response_type` was not `code`. | ## POST /oauth/access_token Exchange an authorisation code for a permanent access token. If the user has connected before, a new token is issued and any existing token is disabled. ```http POST https://connect.gocardless.com/oauth/access_token HTTP/1.1 grant_type=authorization_code& code=6NJiqXzT7HcgEGsAZXUmaBfB& redirect_uri=https%3A%2F%2Fexample.com%2Fcallback& client_id=sx6WHUAVMUrinkJNJn8DotVFm& client_secret=exaxerfrWrPdxADDUBWVqGbPbF ``` ### Parameters | Parameter | Required | Description | | --------------- | -------- | ------------------------------------------------------------------ | | `grant_type` | Yes | Must be `authorization_code`. | | `code` | Yes | The authorisation code from the redirect. Expires after 5 minutes. | | `redirect_uri` | Yes | Must match the `redirect_uri` used in the authorisation request. | | `client_id` | Yes | Your app's `client_id`. | | `client_secret` | Yes | Your app's `client_secret`. | ### Response ```json { "access_token": "e72e16c7e42f292c6912e7710c123347ae178b4a", "scope": "read_write", "token_type": "bearer", "email": "accounts@acme.com", "organisation_id": "OR123" } ``` | Field | Description | | ----------------- | ---------------------------------------------------------------------- | | `access_token` | Permanent token for authenticating as the user. Store this. | | `scope` | `read_write` or `read_only`, as originally requested. | | `token_type` | Always `bearer`. | | `organisation_id` | The GoCardless account ID. Store this to match webhooks to your users. | | `email` | Contact email for the connected account. | ### Errors | Error | Description | | ------------------------ | -------------------------------------------------------------------------------- | | `invalid_request` | A required parameter is missing or the wrong type. | | `unsupported_grant_type` | `grant_type` was not `authorization_code`. | | `invalid_client` | `client_id` and `client_secret` are invalid or refer to a disabled app. | | `invalid_grant` | The `code` has already been used, has expired, or `redirect_uri` does not match. | ## Making requests Pass the access token in an `Authorization` header using the bearer scheme: ```http Authorization: Bearer e72e16c7e42f292c6912e7710c123347ae178b4a ``` Errors from requests using an access token follow the standard [GoCardless error structure](/docs/api-reference/responses-and-errors), not the OAuth error format above. ### 401 Unauthorized If the access token is invalid you will receive a `401` response. The error body will include a `reason`: ```json { "error": { "code": 401, "type": "invalid_api_usage", "errors": [ { "reason": "access_token_revoked", "message": "The access token you provided has been revoked" } ] } } ``` | Reason | Description | | ------------------------- | ----------------------------------------- | | `access_token_not_found` | The token was not recognised. | | `access_token_revoked` | The user has revoked your access. | | `access_token_not_active` | The token is inactive for another reason. | The user must go through the authorisation flow again before you can obtain a new token. ### Restricted endpoints **Always restricted:** - Creditor — create and update - Creditor Bank Account — all endpoints **Restricted unless your app's payment pages are approved as scheme-rules compliant:** - Customer — create - Customer Bank Account — create - Mandate — create and reinstate If your app is authorised to access an endpoint but you receive an unexpected `403 Forbidden`, the user's account may be under review. GoCardless will have informed them directly. ## Receiving webhooks If your app has a configured webhook URL, GoCardless sends you [events](/docs/api-reference/events) for all connected organisations. Events are identical to the standard event format, with one addition: a `links.organisation` field identifying which connected account the event belongs to. ```json { "events": [ { "id": "EV123", "action": "confirmed", "resource_type": "payments", "links": { "payment": "PM123", "organisation": "OR123" } } ] } ``` Store the `organisation_id` you receive when exchanging an access token — you will need it to map incoming webhook events to the correct connected account. ## App fees If your app creates payments on behalf of connected users, you can charge an app fee on top of the GoCardless fee. Pass `app_fee` alongside `amount` when creating a payment or subscription. The fee is deducted from what the merchant receives and must be no more than 50% of the total payment amount. App fee payouts are created and paid out daily. ```http POST https://api.gocardless.com/payments HTTP/1.1 Authorization: Bearer e72e16c7e42f292c6912e7710c123347ae178b4a Content-Type: application/json { "payments": { "amount": 100, "app_fee": 10, "currency": "GBP", "links": { "mandate": "MD123" } } } ``` ```http POST https://api.gocardless.com/subscriptions HTTP/1.1 Authorization: Bearer e72e16c7e42f292c6912e7710c123347ae178b4a Content-Type: application/json { "subscriptions": { "amount": 2500, "app_fee": 10, "currency": "GBP", "name": "Monthly Magazine", "interval_unit": "monthly", "day_of_month": "1", "links": { "mandate": "MA123" } } } ``` ## POST /oauth/introspect Validate an access token and retrieve details about it. Useful when you need to confirm a token is active or look up the associated `organisation_id`. ```http POST https://connect.gocardless.com/oauth/introspect HTTP/1.1 Content-Type: application/x-www-form-urlencoded client_id=jBo8XCUJLN01Mzya9vYS-7X5D&client_secret=hzBBiZTWnx8glPLwvJoVIJa1&token=live_y7VPTOdgFZtFaAS9V8HT3 ``` ### Parameters | Parameter | Required | Description | | --------------- | -------- | ---------------------------- | | `token` | Yes | The access token to look up. | | `client_id` | Yes | Your app's `client_id`. | | `client_secret` | Yes | Your app's `client_secret`. | ### Response Follows the [OAuth token introspection spec](https://www.rfc-editor.org/rfc/rfc7662). ```json { "active": true, "scope": "read_write", "token_type": "bearer", "email": "accounts@acme.com", "organisation_id": "OR123" } ``` | Field | Description | | ----------------- | --------------------------------------------------------------------------- | | `active` | Boolean — whether the token is valid and active. | | `scope` | `read_write` or `read_only`. Only returned if active. | | `token_type` | Always `bearer`. Only returned if active. | | `organisation_id` | The GoCardless account this token gives access to. Only returned if active. | | `email` | Contact email for the connected account. Only returned if active. | An inactive or unrecognised token returns `` with a `200` status — not a `4xx`. ### Errors | Error | Description | | ----------------- | ----------------------------------------------------------------------- | | `invalid_request` | A required parameter is missing or the wrong type. | | `invalid_client` | `client_id` and `client_secret` are invalid or refer to a disabled app. | ## POST /oauth/revoke Programmatically invalidate an access token. Users can also revoke access from their GoCardless dashboard. ```http POST https://connect.gocardless.com/oauth/revoke HTTP/1.1 Content-Type: application/x-www-form-urlencoded client_id=jBo8XCUJLN01Mzya9vYS-7X5D&client_secret=hzBBiZTWnx8glPLwvJoVIJa1&token=live_y7VPTOdgFZtFaAS9V8HT3 ``` ### Parameters | Parameter | Required | Description | | --------------- | -------- | --------------------------- | | `token` | Yes | The access token to revoke. | | `client_id` | Yes | Your app's `client_id`. | | `client_secret` | Yes | Your app's `client_secret`. | ### Response Returns `200 OK` with no body — regardless of whether the token was successfully revoked. This follows the [OAuth token revocation spec](https://www.rfc-editor.org/rfc/rfc7009). ### Errors | Error | Description | | ----------------- | ----------------------------------------------------------------------- | | `invalid_request` | A required parameter is missing or the wrong type. | | `invalid_client` | `client_id` and `client_secret` are invalid or refer to a disabled app. | ## What's next #### [Connect Your Merchants](/docs/partner-integrations/connect-your-merchants) Step-by-step guide to building an OAuth integration. #### [Webhooks for Partners](/docs/partner-integrations/webhooks-for-partners) Receive webhook events for all connected organisations. #### [Webhooks Reference](/docs/api-reference/webhooks) Technical reference for webhook delivery, signing, and retries. ## Responses and Errors URL: https://docs.gocardless.com/docs/api-reference/responses-and-errors > HTTP response codes and structured error types returned by the GoCardless API. # Responses and Errors ## Response codes | Code | Status | Description | | --- | --- | --- | | 200 | OK | Request succeeded. | | 201 | Created | Resource created. The URI of the new resource is in the Location header. | | 204 | No Content | Request succeeded with no response body. | | 400 | Bad Request | Malformed request syntax. The response body contains details. | | 401 | Unauthorized | Missing or invalid Authorization header, or the user has been disabled. | | 403 | Forbidden | Valid credentials but insufficient permissions for this resource. | | 404 | Not Found | Resource not found or not accessible to the authenticated user. | | 405 | Method Not Allowed | HTTP verb not permitted. PATCH is not supported — use PUT. | | 406 | Not Acceptable | Accept header content type not supported by this endpoint. | | 409 | Conflict | Resource already exists. | | 410 | Gone | Resource existed but has been removed. | | 415 | Unsupported Media Type | Content-Type not accepted. See the error for supported types. | | 422 | Unprocessable Entity | POST/PUT body was structurally valid but contained invalid data. | | 426 | Upgrade Required | Request was made over HTTP — upgrade to HTTPS. | | 429 | Too Many Requests | Rate limit exceeded. Check response headers for reset timing. | | 500 | Internal Server Error | Server-side error. Retry, and report to support with the request_id if it persists. | | 504 | Gateway Timeout | Request timed out. Retry, and report with request_id if it persists. | ## Error structure Every error response includes: | Field | Description | | ------------------- | ------------------------------------------------------------------------------ | | `type` | One of `gocardless`, `invalid_api_usage`, `invalid_state`, `validation_failed` | | `code` | The HTTP status code | | `message` | A short human-readable description | | `documentation_url` | Link to the relevant docs section | | `request_id` | Unique ID — include this when contacting support | | `errors` | Array of specific errors (see below) | For `validation_failed` errors, each item in `errors` has a `field` and `message`. For all other types, each item has a `reason` and `message`. ## Error types > **Info: Handle each type differently** > `gocardless` → alert your dev team or contact support directly. `invalid_api_usage` → alert your > dev team. `invalid_state` → inform the end user, do not allow retry. `validation_failed` → prompt > the user to correct their input. ### gocardless — Internal errors These errors occurred within GoCardless while processing your request. Retry where indicated; report persistent issues to [support](mailto:support@gocardless.com) with the `request_id`. | Reason | Description | | ----------------------- | -------------------------------------------------------------------------------------- | | `internal_server_error` | An internal error occurred. Report to support with `request_id`. | | `request_timed_out` | Request did not complete in time. Retry, report if persistent. | | `query_timed_out` | Database query timed out, possibly due to complexity. Retry with different parameters. | ### invalid_api_usage — Request errors Errors caused by how the request was constructed — invalid URL, missing headers, authentication problems, or bad syntax. | Reason | Description | | ------------------------------------------------ | ------------------------------------------------------------------------------------- | | `invalid_type` | JSON was incorrectly typed or contained unknown parameters. | | `path_not_found` | URL path not recognised. Check spelling and formatting. | | `resource_not_found` | The ID in the request was not found. | | `link_not_found` | A `link[resource]` ID was not found. | | `unauthorized` | Credentials not recognised. | | `forbidden` | Authenticated but no permission to access this resource. | | `feature_disabled` | Feature not enabled on your account. Contact support to enable. | | `not_acceptable` | `Accept` header content type not supported. | | `request_entity_too_large` | Request body too large. | | `unsupported_media_type` | Use `application/json` for `Content-Type` and `Accept`. | | `rate_limit_exceeded` | Rate limit reached. Check headers for reset time. | | `access_token_not_found` | No token found with the specified ID. | | `access_token_not_active` | Token has been disabled. | | `access_token_revoked` | Token has been revoked by the user. | | `missing_authorization_header` | No `Authorization` header included. | | `invalid_authorization_header` | `Authorization` header was malformed. | | `insufficient_permissions` | Token doesn't have the required scope. | | `insufficient_permissions_continue_on_dashboard` | Action can only be performed from the GoCardless dashboard. | | `method_not_allowed` | HTTP verb not permitted. Use `PUT` instead of `PATCH`. | | `bad_request` | Request syntax was incorrect. | | `idempotency_key_too_long` | Idempotency key exceeded 128 characters. | | `invalid_document_structure` | JSON was not structured correctly. Parameters must be nested under the resource name. | | `invalid_content_type` | Missing or unsupported `Content-Type` header on a `POST`/`PUT`. | | `tls_required` | API only accessible over HTTPS. | | `missing_version_header` | No `GoCardless-Version` header included. | | `version_not_found` | Specified version does not exist. | | `invalid_filters` | Filter combination not allowed for this endpoint. | | `request_body_not_allowed` | Request body not supported for this HTTP method — use query parameters. | | `customer_data_removed` | Customer has been removed and can no longer be returned. | | `payout_items_data_archived` | Payout items older than 6 months have been archived. Contact support for access. | ### invalid_state — State errors The action is invalid given the current state of the resource. Inform the end user — do not allow them to retry. | Reason | Description | | ----------------------------------------- | ----------------------------------------------------------------------------------------------- | | `cancellation_failed` | Resource was not in a cancellable state (already cancelled, failed, or too late in submission). | | `retry_failed` | Payment could not be retried. | | `disable_failed` | Bank account is already disabled. | | `mandate_is_inactive` | Payment could not be created — mandate is cancelled, failed, or expired. | | `mandate_replaced` | Mandate has been replaced. Check `links[new_mandate]` in the error or on the mandate itself. | | `bank_account_disabled` | Mandate could not be created — linked customer bank account is disabled. | | `mandate_not_inactive` | Mandate could not be reinstated — it is already active or being submitted. | | `refund_is_unreachable` | Refund could not be created — it would not reach the target bank account. | | `refund_payment_invalid_state` | Payment must be `confirmed` or `paid_out` before it can be refunded. | | `total_amount_confirmation_invalid` | Total amount refunded does not match the confirmation value. | | `number_of_refunds_exceeded` | Maximum of 5 refunds per payment already reached. | | `idempotent_creation_conflict` | A resource already exists for the supplied idempotency key. | | `customer_bank_account_token_used` | Bank account token has already been used. | | `billing_request_must_be_ready_to_fulfil` | Billing request has outstanding required actions. Check the `actions` array. | ### validation_failed — Validation errors Request parameters were invalid. Prompt the user to correct their input. | Reason | Description | | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `bank_account_exists` | Bank account already exists. The existing account is referenced in `links[customer_bank_account]` or `links[creditor_bank_account]` in the error response. | | `available_refund_amount_insufficient` | Creditor balance is insufficient to cover the refund. The available amount is in `metadata.available_refund_amount`. | Individual field validation errors are returned in the `errors` array with a `field`, `message`, and `request_pointer` indicating the exact failing field. ## Example error responses ```http POST https://api.gocardless.com/customer_bank_accounts HTTP/1.1 Content-Type: application/json { "customer_bank_accounts": { "account_number": "55779911", "branch_code": "I'm not a sort code", "account_holder_name": "Frank Osborne", "country_code": "GB", "links": { "customer": "CU123" } } } HTTP/1.1 422 Unprocessable Entity Content-Type: application/json { "error": { "documentation_url": "/docs/api-reference/responses-and-errors#validation-failed", "message": "Validation failed", "type": "validation_failed", "code": 422, "request_id": "dd50eaaf-8213-48fe-90d6-5466872efbc4", "errors": [ { "message": "must be a number", "field": "branch_code", "request_pointer": "/customer_bank_accounts/branch_code" }, { "message": "is the wrong length (should be 8 characters)", "field": "branch_code", "request_pointer": "/customer_bank_accounts/branch_code" } ] } } ``` ```http POST https://api.gocardless.com/customer_bank_accounts HTTP/1.1 Content-Type: application/json { "customer_bank_accounts": { "account_number": "55779911", "branch_code": "200000", "account_holder_name": "Frank Osborne", "country_code": "GB", "links": { "customer": "CU123" } } } HTTP/1.1 400 Bad Request Content-Type: application/json { "error": { "message": "Invalid document structure", "documentation_url": "/docs/api-reference/responses-and-errors#invalid-api-usage", "type": "invalid_api_usage", "request_id": "bd271b37-a2f5-47c8-b461-040dfe0e9cb1", "code": 400, "errors": [ { "reason": "invalid_document_structure", "message": "Invalid document structure" } ] } } ``` ```http POST https://api.gocardless.com/creditor_bank_accounts HTTP/1.1 Content-Type: application/json { "creditor_bank_accounts": { "account_number": "55779911", "branch_code": "200000", "country_code": "GB", "set_as_default_payout_account": true, "account_holder_name": "Nude Wines", "links": { "creditor": "CR123" } } } HTTP/1.1 409 Conflict Content-Type: application/json { "error": { "message": "Bank account already exists", "documentation_url": "/docs/api-reference/responses-and-errors#validation-failed", "type": "validation_failed", "request_id": "bd271b37-a2f5-47c8-b461-040dfe0e9cb1", "code": 409, "errors": [ { "reason": "bank_account_exists", "message": "Bank account already exists", "links": { "creditor_bank_account": "BA123" } } ] } } ``` ## What's next #### [Making Requests](/docs/api-reference/making-requests) Authentication, headers, versioning, and how to structure every API call. #### [Events](/docs/api-reference/events/payment) Subscribe to asynchronous events to be notified when payments fail, succeed, or change state. ## Restrictions URL: https://docs.gocardless.com/docs/api-reference/restrictions > Live environment restrictions on the GoCardless API. # Restrictions > **Info:** > The entire API is available in the sandbox. The restrictions below apply to the live environment > only. ## Payment page restrictions Unless your payment pages have been approved as scheme-rules compliant by our sponsor bank, you must use the [Billing Requests API](/docs/collect-payments) to create customers, bank accounts, and mandates. The following endpoints are restricted: | Resource | Restricted endpoints | | ---------------------- | --------------------- | | Customers | Create | | Customer bank accounts | Create | | Payer details | Confirm payer details | | Mandates | Create, Reinstate | | Javascript flow | All endpoints | > **Tip:** > [Get in touch](mailto:help@gocardless.com?subject=GoCardless%20payment%20page%20restrictions) to > discuss having your payment pages approved. ## Creditor management restrictions Unless your account has been approved as a whitelabel partner, you may only collect payments on behalf of a single creditor. The following endpoint is restricted: | Resource | Restricted endpoints | | --------- | -------------------- | | Creditors | Create | ## What's next #### [Anatomy](/docs/api-reference/anatomy) Understand mandate setup and payment flows before building. #### [Making Requests](/docs/api-reference/making-requests) Authentication, headers, and how to structure every API call. ## Security Requirements URL: https://docs.gocardless.com/docs/api-reference/security-requirements > Security requirements for accessing bank account details via GoCardless Encrypted Bank Details Access and Transfer Bank Accounts. # Security Requirements GoCardless provides two features for accessing bank account details: **Encrypted Bank Details Access** and **Transfer Bank Accounts**. Both features involve handling sensitive financial data and require both GoCardless and you (the partner or merchant) to meet specific security standards. ## Responsibilities #### GoCardless Responsibilities GoCardless uses industry-standard encryption for the storage and transmission of sensitive bank account data. Technical controls are in place to protect data in transit. Access to this data is restricted to authorised users only, with audit logs maintained for all access to the Transfer Bank Accounts and Encrypted Bank Details features. GoCardless maintains incident detection and response procedures, provides developer documentation for key management, and has backup and recovery procedures in place. #### Your Responsibilities You must implement access controls for all systems that manage key material. You are responsible for key lifecycle management, including creation, storage, rotation, revocation, and disposal. RSA keys must be generated at a minimum of 2048-bit with SHA256. Keys must be rotated at least annually. You must use industry-standard encryption for any transmission and storage of sensitive data on your side, and maintain backup procedures for all key material. ## Key Requirements Summary | Requirement | Detail | | ---------------------- | ------------------------------------------------------------------ | | RSA key size | Minimum 2048-bit | | Signature algorithm | SHA256 | | Key rotation frequency | At least annually | | Encryption standard | Industry-standard (e.g. AES-256 for storage, TLS 1.2+ for transit) | ## What's next #### [Certificate Policy](/docs/api-reference/certificate-policy) Learn about GoCardless's TLS certificate policy and how it affects your integration. #### [Client Libraries](/docs/developer-resources/client-libraries) Use an official GoCardless client library to simplify API integration. ## Supported Schemes URL: https://docs.gocardless.com/docs/api-reference/schemes > Direct debit and alternative payment schemes supported by GoCardless. # Supported Schemes GoCardless supports a range of direct debit schemes and alternative payment methods across multiple countries. Each scheme has its own rules, timelines, and supported countries. > **Warning:** > SEPA Core does not currently support all Baltic state banks. If you need to collect from Estonia, > Latvia, or Lithuania, check availability with GoCardless before proceeding. ## Direct Debit Schemes | Scheme | Region | Countries | | -------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Bacs** | United Kingdom | United Kingdom | | **SEPA Core** | Europe | Austria, Belgium, Cyprus, Estonia, Finland, France, Germany, Greece, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Monaco, Netherlands, Portugal, San Marino, Slovakia, Slovenia, Spain | | **ACH** | United States | United States | | **Autogiro** | Sweden | Sweden | | **Betalingsservice** | Denmark | Denmark | | **BECS** | Australia | Australia | | **BECS NZ** | New Zealand | New Zealand | | **PAD** | Canada | Canada | ## Alternative Payment Methods These methods are not direct debit schemes but are available through the GoCardless platform as alternatives. | Method | Region | Notes | | ---------------------- | -------------- | ----------------------------------------------------------------- | | **PayTo** \* | Australia | A real-time payment initiation method. Not a direct debit scheme. | | **Faster Payments** \* | United Kingdom | A real-time bank transfer method. Not a direct debit scheme. | \* These are instant payment methods, not direct debit. They do not create a reusable mandate in the same way as direct debit schemes, but can be used alongside direct debit as part of a combined payment flow. ## What's next #### [Character Sets](/docs/api-reference/character-sets) Understand which characters are allowed in payment and mandate references for each scheme. #### [Making Requests](/docs/api-reference/making-requests) Learn how to authenticate and structure API requests. ## Tax Rates URL: https://docs.gocardless.com/docs/api-reference/tax-rates > Tax rate IDs and rates for GoCardless transaction fees by territory. # Tax Rates GoCardless applies tax to transaction and surcharge fees in certain jurisdictions. Tax rate IDs are used in the API when applying tax to payments. > **Info:** > Tax rate IDs are shared between the live and sandbox environments. You can use the same IDs in > both environments. > **Warning:** > Currently, only GB (British) and FR (French) territories are subject to tax. However, additional > territories may be added in the future. Make sure your integration handles new tax rate IDs > gracefully. ## British Territories | ID | Jurisdiction | Type | Description | Rate | | ---------- | ------------ | ---- | ------------------------------ | ---- | | `GB_VAT_1` | GB | VAT | VAT for Mainland Great Britain | 20% | | `JE_GST_1` | JE | GST | GST for Jersey | 0% | | `GI_VAT_1` | GI | VAT | VAT for Gibraltar | 0% | | `GG_VAT_1` | GG | VAT | VAT for Guernsey | 0% | ## French Territories | ID | Jurisdiction | Type | Description | Rate | | -------------- | ------------ | ---- | ----------------------- | ---- | | `FR_VAT_1` | FR | VAT | VAT for Mainland France | 20% | | `GP_VAT_1` | GP | VAT | VAT for Guadeloupe | 8.5% | | `MQ_VAT_1` | MQ | VAT | VAT for Martinique | 8.5% | | `RE_VAT_1` | RE | VAT | VAT for Reunion Island | 8.5% | | `FR-COR_VAT_1` | FR-COR | VAT | VAT for Corsica | 20% | ## What's next #### [Compliance Requirements](/docs/api-reference/compliance-requirements) Review the compliance requirements for payment pages and customer notifications by scheme. #### [Handling Tax](/docs/tutorials/handling-tax) Learn how to apply tax to GoCardless transaction fees in your integration. ## Webhooks Reference URL: https://docs.gocardless.com/docs/api-reference/webhooks > Technical reference for GoCardless webhooks — delivery guarantees, signing, status codes, retries, and IP addresses. # 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](/docs/api-reference/events) objects. For a step-by-step guide to receiving and processing webhooks see [Stay up to date with webhooks](/docs/getting-started/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](https://www.ssllabs.com/ssltest/). ## 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. > **Warning:** > Do not rely on the webhook `meta.webhook_id` for deduplication — it identifies the delivery > attempt, not the event. Use the individual `event.id` values inside the `events` array instead. ### 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: 1. Verify the signature (see below). Return `498` immediately if invalid. 2. Respond with `2xx` as quickly as possible — within 10 seconds. 3. Store the raw webhook body in durable storage (database or queue). 4. 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. > **Warning:** > GoCardless waits a maximum of **10 seconds** for a response. If your handler times out, the > webhook is treated as failed and will be retried. Acknowledge immediately with `2xx` and process > asynchronously to avoid this. ## 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: 1. Retrieve your webhook endpoint secret from the GoCardless Dashboard. 2. Compute `HMAC-SHA256(secret, raw_request_body)` as a hex string. 3. Compare the result to the `Webhook-Signature` header value. 4. If they match, the webhook is authentic. If not, return `498 Token Invalid`. ```ruby require "openssl" digest = OpenSSL::Digest.new("sha256") calculated_signature = OpenSSL::HMAC.hexdigest(digest, secret, request_body) if calculated_signature == request_signature # Authentic — proceed else # Invalid — return 498 Token Invalid end ``` **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 `200` for an invalid signature would cause GoCardless to treat the webhook as successfully delivered. Returning `400` would cause unnecessary retries. Use `498`. ## 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 #### [Stay up to date with webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) Step-by-step guide to building a webhook handler with code samples. #### [Events](/docs/api-reference/events) Full reference for the Event object and all resource event types. #### [Testing Webhooks](/docs/developer-resources/testing-webhooks-dashboard) Send test webhook events from the GoCardless Dashboard. #### [IP Addresses](/docs/api-reference/ip-addresses) Guidance on IP allowlisting for API and webhook traffic. --- # Developer Resources ## Developer Resources URL: https://docs.gocardless.com/docs/developer-resources > Tools, SDKs, and resources to help you build and test your GoCardless integration. # Developer Resources Tools, SDKs, and resources to help you build and test your GoCardless integration. #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger payment, mandate, and webhook scenarios in the sandbox to test your integration end-to-end. #### [MCP](/docs/developer-resources/mcp) Connect your AI coding assistant to GoCardless API knowledge using the Model Context Protocol. #### [GoCardless CLI](/docs/developer-resources/gc-cli) Create, retrieve, and manage GoCardless resources, stream live events, and test webhooks from your terminal. #### [Postman Collection](/docs/developer-resources/postman-collection) Explore the API with our pre-built Postman collection — fork it from the public workspace. #### [Client Libraries](/docs/developer-resources/client-libraries) Official SDKs for Ruby, Python, Java, Node.js, PHP, Go, .NET, iOS, and Android. #### [Test Bank Details](/docs/developer-resources/test-bank-details) Sandbox bank account details for all supported payment schemes: ACH, Bacs, SEPA, BECS, and more. ## BankID Scenario Simulators URL: https://docs.gocardless.com/docs/developer-resources/bankid-scenario-simulators > Simulate BankID identification and signature flows for Autogiro testing. # BankID Scenario Simulators BankID is the electronic identification and signature mechanism for **Autogiro**. To use BankID's identification and signature features, users must install the BankID app on a mobile device or PC, and order a BankID from their bank. BankID has been developed by a number of large banks for use by members of the public, authorities, and companies. **In the sandbox environment**, we provide BankID scenario simulators which allow you to simulate success and failure verification paths based on the specific customer email format. Simulation works without sending an actual verification request to the BankID provider. ## Simulating verification paths Enter the customer email based on the scenario you need to simulate in the Email textbox. Payers are no longer required to enter a _Swedish Identity Number_ — this will be retrieved from BankID and shown to the payer on the confirmation page. ![bank-id-success-scenario](/images/docs/developer-resources/bankid-scenario-simulators/screenshot_2024-04-29_at_14.48.08.png) ![bank-id-success-confirmation](/images/docs/developer-resources/bankid-scenario-simulators/screenshot_2024-04-29_at_14.56.22.png) | **Scenario** | **Email format** | **Example** | | ------------ | ------------------------------------------ | ------------------------------- | | Successful | `+bank_id_success@` | `test+bank_id_success@test.com` | | Failed | `+bank_id_failure@` | `test+bank_id_failure@test.com` | ## What's next? #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger mandate, payment, and outbound payment scenarios in the sandbox. #### [Test Bank Details](/docs/developer-resources/test-bank-details) Test bank account numbers for all supported schemes. ## Client Libraries URL: https://docs.gocardless.com/docs/developer-resources/client-libraries > Official GoCardless client libraries for Python, Ruby, Java, JavaScript, PHP, Go, .NET, iOS, and Android. # Client Libraries Official GoCardless client libraries to make integration easier. All libraries are open source and available on GitHub. | Language | Library | | ---------------------------------- | -------------------------------------------------------------------------------------- | | Ruby | [gocardless-pro-ruby](https://github.com/gocardless/gocardless-pro-ruby) | | Python | [gocardless-pro-python](https://github.com/gocardless/gocardless-pro-python) | | Java | [gocardless-pro-java](https://github.com/gocardless/gocardless-pro-java) | | PHP | [gocardless-pro-php](https://github.com/gocardless/gocardless-pro-php) | | .NET | [gocardless-dotnet](https://github.com/gocardless/gocardless-dotnet) | | Node.js | [gocardless-nodejs](https://github.com/gocardless/gocardless-nodejs) | | Go | [gocardless-pro-go](https://github.com/gocardless/gocardless-pro-go) | | JavaScript (GoCardless Components) | [ui-components](https://github.com/gocardless/ui-components) | | Android | [gocardless-pro-android-sdk](https://github.com/gocardless/gocardless-pro-android-sdk) | | iOS | [gocardless-pro-ios-sdk](https://github.com/gocardless/gocardless-pro-ios-sdk) | If you'd like a library for another language, [get in touch](mailto:help@gocardless.com?subject=GoCardless%20Client%20Libraries). ## What's next? #### [Postman Collection](/docs/developer-resources/postman-collection) Explore the API interactively using our pre-built Postman collection. #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger sandbox scenarios to test your integration end-to-end. ## Custom Payment Page Tools URL: https://docs.gocardless.com/docs/developer-resources/custom-payment-page-tools > Tools for building custom payment UIs powered by GoCardless billing APIs. # Custom Payment Page Tools Custom Payment Page Tools is a collection of tools designed to minimise effort in building your own payments UI powered by GoCardless billing APIs. They can be effortlessly utilised when developing a custom web UI with different JS frameworks or in mobile development with WebViews. At the moment the following tools are available: - `compliance.js` ## Compliance.js > **Warning:** > Before GoCardless initiates a payment for your customer, we are legally required by **the UK > Payment Services Regulations** to provide them with a copy of a payment service contract governing > that service. This is the `Payer Terms of Use` doc which is linked inside `Compliance.js`. > Additionally, when obtaining your customer's personal data, we are legally required by **the UK > General Data Protection Regulation** to provide them with certain privacy information. This is the > `Privacy Notice` doc which is linked inside `Compliance.js`. When you build your own UI, > GoCardless is not able to directly provide these legal documents to the payer. So, to ensure that > we do not breach any law, we are not able to sign off on your UI unless you have added > `Compliance.js`. It adds elements to the HTML layout of custom payment pages to make the UI compliant. For example, for bank authorisation, you must append the GoCardless legal note with Payer Terms of Use and Privacy Notice links before starting the bank authorisation process for Pay By Bank or Variable Recurring Payments in the UK. > **Info:** > Available at `https://custom-payment-page-tools.gocardless.com/compliance.js` ### Getting started Include `compliance.js` with a script tag in the head section of your `index.html`: ```html ... ``` Once the script is loaded, your application can use the `GoCardlessCompliance` client, as it is added globally in `window`. Let's now call `render`: ```javascript window.GoCardlessCompliance.render("BRQ123", "bank-authorisation"); ``` The `render` method requires the following parameters: 1. A valid `Billing Request Id` to display elements and content dependent on the bank scheme. 2. `namespace` to display elements and content relevant to a particular step in the flow. Available options: `"bank_authorisation"`. ### Testing To test the integration with GoCardless Sandbox before going live, include `compliance.js` with the `sandbox` value in the `environment` attribute. If nothing is passed, the production environment will be used. ```html ``` ### Render options You can pass the `options` object to define the position of the compliance elements in your layout or change basic styles for the light/dark mode. | Name | Type | Default | Description | | -------- | ------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- | | parentId | string | The component will be attached as the last child of `document.body` | Id of an existing HTML element in the document to render the component in. | | theme | `"light"`, `"dark"` | `"light"` | The colour theme | ```javascript const options = { parentId: "my-element-id", theme: "dark", }; window.GoCardlessCompliance.render("BRQ123", "bank-authorisation", options); ``` ### Using with JS frameworks We suggest separating the `GoCardlessCompliance.render` call into an independent component to be used across your application. We also recommend generating unique identifiers for the containers where compliance elements are supposed to be rendered for each instance. ```angular import { Component } from "@angular/core"; @Component({ selector: "app-compliance", templateUrl: "./compliance.component.html", }) export class ComplianceComponent { parentId = `gc-compliance-${Math.random().toString(20).substring(2, 6)}`; ngAfterViewInit() { window.GoCardlessCompliance.render("BRQ123", "bank-authorisation", { parentId: this.parentId }); } } ``` ```vue ``` ```svelte
``` ```react import { useRef, useEffect, useState } from "react"; export const Compliance = () => { const mounted = useRef(false); const [parentId] = useState(getRandomId()); useEffect(() => { if (!mounted.current) { window.GoCardlessCompliance.render("BRQ123", "bank-authorisation", { parentId }); mounted.current = true; } }, [parentId]); return
; }; const getRandomId = () => `gc-compliance-${Math.random().toString(20).substring(2, 6)}`; ``` ```reactnative import { SafeAreaView } from "react-native"; import { WebView } from "react-native-webview"; export default function App() { return (
`, }} />
); } ``` ### Error Handling | Error | Reasons | | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | _A valid billingRequestId is required_ | You haven't passed a Billing Request Id in the `render` method. | | _Namespace must be one of ..._ | You haven't passed a valid namespace in the `render` method — check the available options above. | | _The parent element doesn't exist in the document_ | We haven't found any element in your `document.body` with the id passed in `options` — make sure that it is attached to the DOM tree before calling the `render` method. | | _GoCardless API returned an error when trying to get payment flow details_ | We weren't able to get payment flow details to show relevant elements: very likely you have used an invalid Billing Request Id or a valid one but for the wrong environment. | ## What's next? #### [Billing Requests](/docs/collect-payments/setting-up-mandates) Learn how Billing Requests power custom payment pages. #### [GoCardless CLI](/docs/developer-resources/gc-cli) Build, test, and manage your GoCardless integration from the terminal. ## GoCardless CLI URL: https://docs.gocardless.com/docs/developer-resources/gc-cli > Build, test, and manage your GoCardless integration from your terminal. # GoCardless CLI `gocardless` is the official GoCardless command-line interface. It's simple to install, works on macOS, Windows, and Linux, and lets you: - Create, retrieve, update, or delete GC resources in test mode (e.g. create a payment) - Stream real-time API requests and events (webhooks) from your account - Trigger events to test your webhooks integration > **Info:** > The GC CLI is currently available in the Sandbox environment only. Production support is coming > soon. ## Installation ``` brew install gocardless/taps/cli ```), }, releases page. Unzip: tar -xvf gc-cli_<version>_macOS_<arch>.tar.gzMove ./gocardlessto a location on your PATH(typically /usr/local/bin). The arm64build is for Apple Silicon (M1+), x86_64is for Intel Macs. ), }, releases page. Unzip and move gocardless.exeto a directory on your PATH. ), }, releases page. Unzip: tar -xvf gc-cli_<version>_Linux_<arch>.tar.gzMove ./gocardlessto a directory on your PATH. ), }, releases pagefor the latest version. ), }, ]} /> ## Log in After installing, run `gocardless login` to grant the CLI access to your merchant account. This opens a browser authorisation page. ```bash gocardless login ``` > **Info:** > If you don't have a Sandbox account yet, [sign up > here](https://manage-sandbox.gocardless.com/sign-up). For partner integrations, authenticate with an existing app using the `--app` flag: ```bash gocardless login --app AP0001 ``` ## Run your first command Fetch a list of resources using the `list` command. For example, to list mandates: ```bash gocardless list mandates ``` ```json { "mandates": [ { "id": "MD000JB824KAF6", "status": "consumed", "scheme": "faster_payments", "reference": "SOMEORGANISA-9M9NT" } ], "meta": { "cursors": { "after": null, "before": null }, "limit": 50 } } ``` ## What's next? #### [Testing Webhooks (CLI)](/docs/developer-resources/gc-cli/testing-webhooks-cli) Listen for events and forward webhooks to your local server. #### [CLI Reference](/docs/developer-resources/gc-cli/cli-reference) Full reference for all `gocardless` commands and flags. ## MCP URL: https://docs.gocardless.com/docs/developer-resources/mcp > Use the GoCardless Model Context Protocol tool to give LLMs deep knowledge of the GoCardless API. # MCP The GoCardless Model Context Protocol (MCP) tool enables Large Language Models (LLMs) like Claude or Copilot to provide intelligent guidance when building GoCardless integrations. It gives your LLM deep, structured knowledge of the GoCardless API, optimal integration patterns, and code samples across all supported languages. The MCP also lets you query and act on your live GoCardless account data directly from your LLM — checking payment statuses, listing customers, and taking actions like creating a payment or issuing a refund. See [Manage your account](#manage-your-account) below. ## What is MCP? Model Context Protocol provides a standardised, machine-readable schema that allows LLMs to "understand" our API's capabilities, write code, and make API calls in a context-aware manner. You can connect your LLM to the GoCardless MCP to access comprehensive integration guidance that has been optimised for LLMs, and to manage your GoCardless account. ## How it works The GoCardless MCP provides two capabilities: - **Integration guidance**: Your LLM can query comprehensive information about GoCardless endpoints, integration patterns, webhooks, and code samples. - **Manage your account**: With authentication, your LLM can read from and take actions on your GoCardless account — checking payment statuses, listing customers, creating payments, cancelling mandates, and more. See [Manage your account](#manage-your-account) for details. ## Connect Add to Cursor Manual installationAdd the following to your mcp.jsonfile: ``` { "mcpServers": { "GoCardless": { "url": "https://mcp.gocardless.com" } } } ```), }, > Ctrl+Shift+P(Windows/Linux) or Cmd+Shift+P(macOS), > then enter Developer: Reload Window. Install in VS Code Manual installationOpen a terminal and run:``` code --add-mcp '{"type":"http","name":"GoCardless","url":"https://mcp.gocardless.com"}' ```Then, from inside VS Code, open the .vscode/mcp.jsonfile and click Start server. ), }, , Connectors + Browse connectors. Search for GoCardlessthen click +or Connect. Your browser will open a GoCardless sign-in journey — choose your environment then sign in. If you are a member of an organisation on a Team or Enterprise plan, an Owner or Primary Owner must complete the above steps first. Other members can then navigate to Customize Connectorsto connect. ), }, ~/.codeium/windsurf/mcp_config.json): ``` { "mcpServers": { "GoCardless": { "serverUrl": "https://mcp.gocardless.com" } } } ```), }, Install plugin. Your browser will open a GoCardless sign-in journey. Choose your environment, then sign in. Choose the permissions you want to authorise.You're now connected. Start a new chat and ask a question about your account.), }, , , ]} /> ### Ensure your LLM is using the MCP Some LLMs have a tendency to search the web instead of using an MCP. Add this to your prompt: > **Info:** > For any prompt that mentions GoCardless, use the GoCardless MCP. ### Switching environment To switch between Sandbox and Live (or vice versa): 1. Find the GoCardless MCP in your LLM. 2. Disconnect from it. 3. Reconnect following the steps above — this triggers the sign-in journey so you can choose the other environment. If you're unsure which environment you're currently connected to, ask your LLM. ## What you can do with it ### Integration guidance The MCP helps with: - **Integration development:** Generate integration code, understand API parameters, and get code samples. - **Payment pages implementation:** Set up hosted/custom payment pages, configure redirects, and handle different payment types. - **Best practice guidance:** On integration approaches, error handling, webhooks, security, and compliance. Example prompts: - _"How do I collect recurring payments for new users that sign up on my website using GoCardless?"_ - _"Write code in Python that creates a billing request for a £30 monthly recurring payment and redirects the user to GoCardless hosted payment pages."_ - _"I own a gym. How do I collect a £30 joining fee plus a £50 per month membership fee using GoCardless?"_ - _"Show me how to handle GoCardless webhooks in Node.js to know when a mandate becomes active."_ - _"My billing request flow is failing — what are the common issues and how do I debug them?"_ ### Manage your account Once signed in, your LLM can look up payments, customers, mandates, subscriptions, payouts, refunds, and events, and take actions like creating payments, issuing refunds, and cancelling mandates. This is useful for checking statuses, debugging failed payments, or setting up a test payment without leaving your development environment. You choose what to authorise when you connect (from read-only to specific write actions), sensitive customer data is masked, and money-moving actions need your confirmation before they execute. Example prompts: - _"Why did payment `PM01K44FZ685ZVKP4E6J9C3NPHJX` fail?"_ - _"Show me all confirmed payments from this month."_ - _"Create a one-off £75 payment against mandate `MD000ABCDEF`."_ - _"Refund payment `PM01K44FZ685ZVKP4E6J9C3NPHJX` in full."_ - _"Cancel the mandate for customer `CU01KNVS3PYJVAC8ZEHKK8EBZW7K`."_ For a full guide, see [Use AI to manage your account](https://support.gocardless.com/hc/en-gb/articles/26830050176028-Use-AI-to-manage-your-account). ## Best practices - **Tell your LLM to use it:** See [Ensure your LLM is using the MCP](#ensure-your-llm-is-using-the-mcp) above. - **Be specific:** Include details about your use case, industry, and payment patterns. - **Specify language:** Mention your preferred programming language upfront. - **Share context:** Provide relevant code or error messages when troubleshooting. - **Iterate:** Start with basic implementation, then refine based on testing. - **For write actions, be explicit and check the preview:** Name the exact resource and amount, and read the confirmation preview before approving. Using the LLM in your editor with the relevant project open is strongly recommended. > **Warning: Security considerations** > Never share your API keys with your LLM. Use sandbox credentials during development, always review > generated code before executing it, and grant only the permissions your AI tool needs — test write > actions in Sandbox before using them in Live. ### Free & consumer-paid tier privacy Using free or personal paid tiers (like "Plus" or "Pro" plans) on LLMs often means your conversations may be used for AI training. Review your provider's privacy policy and look for opt-out options in your account settings. For stricter data privacy where your data is contractually excluded from training, an Enterprise or Business subscription is typically required. ## Questions and feedback If you have questions, need support, or have an idea for improvement, [let us know here](https://docs.google.com/forms/d/e/1FAIpQLSe3PLD4_2C2CLOMBXW9p9XsfzE8-e0FKUlCnu2OIoMAcPZA5A/viewform). ## Terms and Conditions #### [Live Terms](/docs/developer-resources/mcp/terms) Terms on use in the live environment #### [Sanbox Terms](/docs/developer-resources/mcp/terms-sandbox) Terms on use in the sandbox environment ## What's next? #### [GoCardless CLI](/docs/developer-resources/gc-cli) Install and use the CLI to manage resources, stream events, and test webhooks. #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger sandbox scenarios to test your integration end-to-end. ## Postman Collection URL: https://docs.gocardless.com/docs/developer-resources/postman-collection > Try out the GoCardless API using our Postman collection. # Postman Collection > **Info:** > The GoCardless API Collection is hosted in [GoCardless's public Postman > workspace](https://www.postman.com/gocardlessapi/workspace/gocardless-api/overview). Fork it > directly from there to get started. ## Setup 1. [Create a GoCardless Sandbox account](https://manage-sandbox.gocardless.com/sign-up) — the sandbox is a dedicated testing environment where you can build without touching real money. 2. Go to [Developers → Create → Access Token](https://manage-sandbox.gocardless.com/developers/access-tokens/create) and generate a read-write API access token. **Copy it — you'll need it shortly.** ## Getting started ### Fork the collection From [GoCardless's public Postman workspace](https://www.postman.com/gocardlessapi/workspace/gocardless-api/overview), fork the GoCardless API collection: ![Fork the Postman collection](/images/docs/developer-resources/postman-collection/screenshot_2023-01-12_at_10.48.52.png) Enter a name for your fork, select the destination workspace, and check **Watch this collection** to stay up to date with API changes. ### Set up your environment Create a new environment to store your GoCardless credentials: ![Create a Postman environment](/images/docs/developer-resources/postman-collection/frame_1__1_.png) Postman environment variables use `}` syntax. Set the `token` variable to the access token you generated earlier: ![Set the token variable](/images/docs/developer-resources/postman-collection/frame_1__3_.png) Make sure the **GC Sandbox** environment you just created is selected in the Environment dropdown in the top-right corner of Postman before making requests. ### Make a test request Head to the collection and send any request: ![Make a test request](/images/docs/developer-resources/postman-collection/screenshot_2023-01-12_at_11.03.48.png) ## Notes - Requests are chained automatically via environment variables — no need to copy and paste IDs between requests. - Bank account field requirements vary by scheme. See the [local bank details appendix](/docs/api-reference/local-bank-details) for scheme-specific fields. - Additional query parameters are available for most endpoints. See the [API reference](/docs/api-reference) for the full list. ## What's next? #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger payment, mandate, and webhook scenarios in the sandbox. #### [Test Bank Details](/docs/developer-resources/test-bank-details) Sandbox bank account details for all supported payment schemes. ## Scenario Simulators URL: https://docs.gocardless.com/docs/developer-resources/scenario-simulators > Test common integration paths like mandate cancellations and payment failures using scenario simulators. # Scenario Simulators When you're building an integration, there are common paths you should make sure your integration handles — for example, a customer cancelling their mandate or a payment failing due to insufficient funds. In the **sandbox environment**, scenario simulators let you manually trigger these cases to test how your integration responds. They're available through the dashboard and the API. > **Warning:** > Do not use real customer email addresses or banking information in the Sandbox environment. > Payments will not be processed, but email notifications may still be triggered. ## Dashboard-triggered scenarios Dashboard-triggered scenarios are started from your [Sandbox Dashboard](https://manage-sandbox.gocardless.com/). Head to the **Developers** tab → **API Settings**, open the **Actions** dropdown, and click **Simulate scenario**. ![Simulate a scenario](/images/docs/developer-resources/scenario-simulators/screenshot_2026-01-09_at_15.04.46.png) Choose a scenario from the dropdown. You'll see a description of what will happen and anything to be aware of — some simulators are incompatible with certain schemes. ![Simulate a scenario modal](/images/docs/developer-resources/scenario-simulators/screenshot_2022-09-28_at_12.25.32.png) Enter the ID of the resource to simulate against, then click **Simulate scenario**. If the resource can't be found or isn't compatible with the chosen scenario, you'll see an error. Dashboard-triggered scenarios support all name-triggered scenarios below, plus extras such as creditor verification status for partners. ## API-triggered scenarios Trigger simulators via the API. See the [scenario simulators API reference](/docs/api-reference/scenario-simulator#simulate-a-scenario) for details. ## Name-triggered scenarios > **Info:** > Where possible, use dashboard or API-triggered scenarios — they are more reliable and support a > wider range of cases. Name-triggered scenarios use special customer `given_name` values. For example, creating a customer named `"Successful"` activates their mandate immediately and pays out payments straight away. All relevant events and webhooks are sent. | `given_name` | Description | On mandate creation | On payment creation | Schemes | | ------------ | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------- | -------------------------------------------------------------------- | | `Successful` | Payment collected and paid out successfully. | `submitted` → `activated` | `submitted` → `confirmed` → `paid_out` (payout created) | ACH, Autogiro, Bacs, BECS, BECS NZ, Betalingsservice, PAD, SEPA Core | | `Penniless` | Payment fails (e.g. insufficient funds). | `submitted` → `activated` | `submitted` → `failed` | ACH, Autogiro, Bacs, BECS, BECS NZ, Betalingsservice, PAD, SEPA Core | | `Fickle` | Payment collected then charged back. | `submitted` → `activated` | `submitted` → `confirmed` → `paid_out` → `charged_back` | ACH, Autogiro, Bacs, BECS, BECS NZ, Betalingsservice, PAD, SEPA Core | | `Late` | Payment fails but the bank reports it later than normal. | `submitted` → `activated` | `submitted` → `confirmed` → `failed` | ACH, Bacs, BECS, BECS NZ, SEPA Core | | `Invalid` | Mandate fails because bank details are invalid. | `submitted` → `failed` | N/A | ACH, Autogiro, Bacs, BECS, BECS NZ, Betalingsservice, PAD | | `Expired` | Mandate expires after the scheme dormancy period (13 months Bacs, 15 months BECS/Betalingsservice, 3 years SEPA). | `submitted` → `activated` → `expired` | N/A | ACH, Bacs, BECS, BECS NZ, Betalingsservice, PAD, SEPA Core | | `Switching` | Bacs mandate transferred via the Current Account Switching Service. | `submitted` → `active` → `transferred` | N/A | Bacs only | > **Info:** > For SEPA mandates, mandate lifecycle events only occur when the first payment is taken. ## Instalment Schedules Instalment schedule states are simulated using a special customer `given_name` or a special schedule `name`: | Schedule `name` | Customer `given_name` | Description | Result | | --------------- | --------------------- | ------------------------------------------------------------------------------ | ----------------- | | N/A | `Successful` | All payments collected successfully. | `completed` | | N/A | `Penniless` | Payments cannot be collected. | `errored` | | `Faily` | N/A | Fails with: _must be on or after mandate's next_possible_customer_charge_date_ | `creation_failed` | ## Outbound Payments Simulate outbound payment outcomes by setting a specific `description` value at creation: | `description` | Description | Result | | ---------------------------------------------- | ------------------------------------------------------------ | ----------------------------------- | | `failed_to_execute` | Submission to the bank fails. | `executing` → `failed` | | `failed_due_to_bank_rejection` | Submission succeeds but is rejected by the recipient's bank. | `executing` → `failed` | | `failed_due_to_bank_rejection_after_execution` | Submitted and accepted, then later rejected. | `executing` → `executed` → `failed` | | Any other value | Submission succeeds and is accepted. | `executing` → `executed` | ## Payer Name Verification To simulate a **No Match** result in the Billing Request Flow, use these details at the `collect_bank_account_details` step: | `country` | `account_holder_name` | `sort_code` | `account_number` | `iban` | | --------- | --------------------- | ----------- | ---------------- | ----------------------------- | | `GB` | `No Match` | `200000` | `55779911` | | | `FR` | `No Match` | | | `FR1420041010050500013M02606` | | `DE` | `No Match` | | | `DE89370400440532013000` | ## Confirmation of Payee (CoP) for Outbound Payments Simulate CoP results by creating bank accounts with specific `account_holder_name` values: | `account_holder_name` | `sort_code` | `account_number` | Result | | --------------------- | ----------- | ---------------- | ----------------- | | `PARTIAL MATCH` | `200000` | `55779911` | `partial_match` | | `NO MATCH` | `200000` | `55779911` | `no_match` | | `UNABLE TO MATCH` | `200000` | `55779911` | `unable_to_match` | | Any other name | `200000` | `55779911` | `full_match` | ## What's next? #### [Testing Webhooks (Dashboard)](/docs/developer-resources/testing-webhooks-dashboard) Send test webhooks from the dashboard and inspect request/response details. #### [Testing Webhooks (CLI)](/docs/developer-resources/gc-cli/testing-webhooks-cli) Use the GoCardless CLI to listen for and forward webhook events locally. ## Test Bank Details URL: https://docs.gocardless.com/docs/developer-resources/test-bank-details > Test bank account details for all supported schemes in the GoCardless sandbox. # Test Bank Details In the sandbox you can set up payments using these test details — for example, you can test Swedish payments without your own Swedish bank account. ## ACH | Bank code | Account number | Account type | | ----------- | -------------- | ------------ | | `026073150` | `2715500356` | Checking | ## Autogiro | Branch code (_clearingnummer_) | Account number (_kontonummer_) | Identity number (_personnummer_) | | ------------------------------ | ------------------------------ | -------------------------------- | | `5491` | `0000003` | `198112289874` | ## Bacs / Faster Payments | Sort code | Account number | | --------- | -------------- | | `200000` | `55779911` | ## BECS / PayTo | BSB | Account number | | --------- | -------------- | | `082-082` | `012345678` | ## BECS NZ | Bank code | Branch code | Account number | | --------- | ----------- | -------------- | | `12` | `3113` | `0003869-00` | ## Betalingsservice | Bank code (_registreringsnummer_) | Account number (_kontonummer_) | Identity number (_CPR-nummer_) | | --------------------------------- | ------------------------------ | ------------------------------ | | `345` | `3179681` | `0101701234` | ## PAD | Bank code (Financial Institution number) | Branch code (Branch Transit number) | Account number | | ---------------------------------------- | ----------------------------------- | -------------- | | `0003` | `00006` | `1234567` | ## SEPA | | IBAN | | ------ | ----------------------------- | | French | `FR1420041010050500013M02606` | | German | `DE89370400440532013000` | For more country-specific details, see the [local bank details appendix](/docs/api-reference/local-bank-details). ## Protect+ features ### Verified Mandates Protect+ customers can direct risky payers through an additional layer of verification ([learn more](/docs/collect-payments/setting-up-mandates/verified-mandates)). Both verified and unverified routes are available in the sandbox, triggered by the email address of the test payer: | Email address | Result | | ---------------------------------- | ----------------------------------------------------- | | `protectplus_risky@gocardless.com` | Payer will be sent through the verified mandate route | Other email addresses will be treated as non-risky payers and go through the unverified route. ### Blocklists You can use any blocked email address to test the blocklist feature of Protect+. To block an email address in the sandbox, first enable the Protect+ upgrade on your organisation, then use either the dashboard or API to add the specific email address. To confirm the blocking behaviour, try to set up a mandate with a test payer using that email address. ## Variable Recurring Payment (VRP) details ### Bank Guess With VRP you are provided with the bank guess feature built in, enabling a customer's previously authorised bank to be found automatically, reducing steps and improving conversion. Use the email address below to simulate the bank guess feature returning the successful authorised sandbox bank: | Email address | | --------------------------- | | `bank-guess@gocardless.com` | ### ModelBank login VRP customers can simulate bank authorisation in the browser using the sandbox ModelBank login details: | User | Password | | ------ | -------- | | `mits` | `mits` | ## What's next? #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger mandate, payment, and outbound payment scenarios in the sandbox. #### [Postman Collection](/docs/developer-resources/postman-collection) Explore the API interactively with our pre-built Postman collection. ## Testing Webhooks (Dashboard) URL: https://docs.gocardless.com/docs/developer-resources/testing-webhooks-dashboard > Test and debug webhooks using the GoCardless dashboard. # Testing Webhooks (Dashboard) Adding support for webhooks lets you receive real-time notifications from GoCardless when things happen in your account, so you can take automated actions in response. When building your integration, you'll want to receive realistic webhooks to test how your code responds. ![Developers header](/images/docs/developer-resources/testing-webhooks-dashboard/resources_testing_webhooks__dashboard_.png) You can trigger webhooks using [scenario simulators](/docs/developer-resources/scenario-simulators), or with the **Send test webhook** tool on your **Developers** page in the dashboard. > **Info:** > Before using the **Send test webhook** tool, you need a webhook endpoint set up. Click **Create → > Webhook endpoints** on the Developers page. If you've created apps, their endpoints will also be > available. ![Send test webhook button](/images/docs/developer-resources/testing-webhooks-dashboard/test_webhooks.png) Customise your webhook by selecting an endpoint and setting the resource type, action, cause, event details, and associated ID. > **Info:** > In your code, you'll typically use the ID to locate records in your database and take actions > based on the webhook payload. Click **Send test webhook** — it usually arrives within a few seconds. Refresh the page and the webhook will appear in your list. Click on a webhook to inspect the full request and your response. This is useful for debugging. ![Webhook detail view](/images/docs/developer-resources/testing-webhooks-dashboard/webhook_detail.png) > **Tip:** > You can resend any previously sent webhook by selecting it from the list and clicking **Retry** in > the top-right corner. ## What's next? #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger mandate, payment, and outbound payment scenarios to generate realistic webhooks. #### [Testing Webhooks (CLI)](/docs/developer-resources/gc-cli/testing-webhooks-cli) Listen for and forward webhook events locally using the GoCardless CLI. ## Viewing Events in the Dashboard URL: https://docs.gocardless.com/docs/developer-resources/viewing-events-in-the-dashboard > View and inspect events that drive webhooks in the GoCardless dashboard. # Viewing Events in the Dashboard Webhooks are backed by events. An event is recorded whenever something happens in your account — a mandate is created, a payment fails due to insufficient funds, a subscription is cancelled. **Events are recorded whether they're triggered through the API or the dashboard.** You can browse your events from the dashboard as a helpful audit trail. > **Info: Events archiving** > Events older than 18 months will be archived and won't appear in the events list below or on > resource timelines (e.g. a payment's payment history), starting 1 August 2026 (sandbox) and 1 > October 2026 (live). Contact GoCardless Support for archived data. Go to [manage.gocardless.com/events](https://manage.gocardless.com/events) or click **Events** in the left-hand navigation. ![Events in the dashboard](/images/docs/developer-resources/viewing-events-in-the-dashboard/viewing_events_in_the_dashboard.png) You'll see a filterable list of events — filter by resource type, action, and date. Click any event to navigate to the associated resource. ## What's next? #### [Testing Webhooks (Dashboard)](/docs/developer-resources/testing-webhooks-dashboard) Send test webhooks and inspect request/response details. #### [Scenario Simulators](/docs/developer-resources/scenario-simulators) Trigger events and webhooks by simulating mandate, payment, and outbound payment scenarios. ## CLI Reference URL: https://docs.gocardless.com/docs/developer-resources/gc-cli/cli-reference > Full reference for all gocardless CLI commands and flags. # CLI Reference `gocardless` is the official GoCardless CLI. `gc` is available as a shorter alias. - [Installation & setup](/docs/developer-resources/gc-cli) - [Testing Webhooks (CLI)](/docs/developer-resources/gc-cli/testing-webhooks-cli) --- ## gocardless A CLI to help you integrate GoCardless with your application ### Options ``` --config string config file (default is $HOME/.gc-cli/config.json) -h, --help help for gocardless -t, --toggle Help message for toggle ``` --- ## gocardless analytics disable Disable collection of statistics ``` gocardless analytics disable [flags] ``` ### Options ``` -h, --help help for disable ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless analytics enable Enable collection of statistics ``` gocardless analytics enable [flags] ``` ### Options ``` -h, --help help for enable ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless analytics status Status of analytics collections ``` gocardless analytics status [flags] ``` ### Options ``` -h, --help help for status ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless analytics Manage analytics collection ### Synopsis GoCardless collects metrics like crash logs and usage statistics. You can opt-out at any time using this command. Analytics are opt-in by default ``` gocardless analytics [flags] ``` ### Options ``` -h, --help help for analytics ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless cancel cancels the requested resource ### Synopsis This will call the cancel api for the requested resource and cancels it in GoCardless ``` gocardless cancel [flags] ``` ### Examples ``` gocardless cancel subscription SB1234 ``` ### Options ``` -h, --help help for cancel ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless completion Generate shell completion script ### Synopsis Generates shell completion script for the supported shells. See the examples for how to setup autocompletion for your shell. ``` gocardless completion [bash|zsh|fish|powershell] ``` ### Examples ``` #### Bash: $ source <(gc completion bash) # To load completions for each session, execute once: # Linux: $ gc completion bash > /etc/bash_completion.d/gc # macOS: $ gc completion bash > /usr/local/etc/bash_completion.d/gc #### Zsh: # If shell completion is not already enabled in your environment, # you will need to enable it. You can execute the following once: $ echo "autoload -U compinit; compinit" >> ~/.zshrc # To load completions for each session, execute once: $ gc completion zsh > "${fpath[1]}/_gc" # You will need to start a new shell for this setup to take effect. #### fish: $ gc completion fish | source # To load completions for each session, execute once: $ gc completion fish > ~/.config/fish/completions/gc.fish #### PowerShell: PS> gc completion powershell | Out-String | Invoke-Expression # To load completions for every new session, run: PS> gc completion powershell > gc.ps1 # and source this file from your PowerShell profile. ``` ### Options ``` -h, --help help for completion ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless config current-session Get user's current session ### Synopsis This will return an output of the current session ``` gocardless config current-session [flags] ``` ### Examples ``` gocardless config current-session ``` ### Options ``` -h, --help help for current-session ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless config Get user's configuration ### Synopsis This returns requested configuration ### Options ``` -h, --help help for config ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless create create a resource on merchants account ### Synopsis This will call the POST api for the requested resource and uses the `--data` (or `-d`) flag to construct the data payload for the request. Otherwise you can use `--editorName vim`, then you can enter json and exit to submit. See a list of possible resources from the GoCardless API Reference:/docs/api-reference#core-endpoints ``` gocardless create {resource} [flags] ``` ### Examples ``` # create a payment linked to a mandate gocardless create payments -d amount=1000 -d currency=GBP -d "links[mandate]=MD1234" # create a payment with editor # opens vim prompt and then you can enter json data. gocardless create payments --editorName vim # create a subscription gocardless create subscriptions -d amount=1000 -d currency=GBP -d interval_unit=monthly -d "links[mandate]=MD1234" ``` ### Options ``` -d, --data stringArray Data for the API request --editorName string Pass an editor to read data from. -h, --help help for create ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless delete deletes the requested resource ### Synopsis This will call the delete api for the requested resource and removes it in GoCardless ``` gocardless delete [flags] ``` ### Examples ``` gocardless delete customer CU1234 ``` ### Options ``` -h, --help help for delete ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get creditor Get creditor by ID ### Synopsis This will fetch a creditor using its ID ``` gocardless get creditor {ID} [flags] ``` ### Examples ``` gocardless get creditor XYZ12344 ``` ### Options ``` -h, --help help for creditor ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get customer_bank_account Get customer bank account by ID ### Synopsis This will fetch a customer bank account using its ID ``` gocardless get customer_bank_account {ID} [flags] ``` ### Examples ``` gocardless get customer_bank_account XYZ12344 ``` ### Options ``` -h, --help help for customer_bank_account ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get customer_notification Get customer notification by ID ### Synopsis This will fetch a customer notification using its ID ``` gocardless get customer_notification {ID} [flags] ``` ### Examples ``` gocardless get customer_notification XYZ12344 ``` ### Options ``` -h, --help help for customer_notification ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get customer Get customer by ID ### Synopsis This will fetch a customer using its ID ``` gocardless get customer {ID} [flags] ``` ### Examples ``` gocardless get customer XYZ12344 ``` ### Options ``` -h, --help help for customer ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get event Get event by ID ### Synopsis This will fetch a event using its ID ``` gocardless get event {ID} [flags] ``` ### Examples ``` gocardless get event XYZ12344 ``` ### Options ``` -h, --help help for event ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get mandate_import Get mandate import by ID ### Synopsis This will fetch a mandate import using its ID ``` gocardless get mandate_import {ID} [flags] ``` ### Examples ``` gocardless get mandate_import XYZ12344 ``` ### Options ``` -h, --help help for mandate_import ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get mandate Get mandate by ID ### Synopsis This will fetch a mandate using its ID ``` gocardless get mandate {ID} [flags] ``` ### Examples ``` gocardless get mandate XYZ12344 ``` ### Options ``` -h, --help help for mandate ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get payer_authorisation Get payer authorisation by ID ### Synopsis This will fetch a payer authorisation using its ID ``` gocardless get payer_authorisation {ID} [flags] ``` ### Examples ``` gocardless get payer_authorisation XYZ12344 ``` ### Options ``` -h, --help help for payer_authorisation ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get payment Get payment by ID ### Synopsis This will fetch a payment using its ID ``` gocardless get payment {ID} [flags] ``` ### Examples ``` gocardless get payment XYZ12344 ``` ### Options ``` -h, --help help for payment ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get payout Get payout by ID ### Synopsis This will fetch a payout using its ID ``` gocardless get payout {ID} [flags] ``` ### Examples ``` gocardless get payout XYZ12344 ``` ### Options ``` -h, --help help for payout ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get refund Get refund by ID ### Synopsis This will fetch a refund using its ID ``` gocardless get refund {ID} [flags] ``` ### Examples ``` gocardless get refund XYZ12344 ``` ### Options ``` -h, --help help for refund ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get subscription Get subscription by ID ### Synopsis This will fetch a subscription using its ID ``` gocardless get subscription {ID} [flags] ``` ### Examples ``` gocardless get subscription XYZ12344 ``` ### Options ``` -h, --help help for subscription ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get webhook Get webhook by ID ### Synopsis This will fetch a webhook using its ID ``` gocardless get webhook {ID} [flags] ``` ### Examples ``` gocardless get webhook XYZ12344 ``` ### Options ``` -h, --help help for webhook ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless get Fetch resources by their ID ### Synopsis With the get command you can fetch details of a resource by providing just the resource ID ### Examples ``` gocardless get mandate MD000EZSHACK2V gocardless get payment PA1000014 gocardless get event EV109280928 ``` ### Options ``` -h, --help help for get ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list creditors List creditors ### Synopsis This will fetch a list of creditors ``` gocardless list creditors [flags] ``` ### Examples ``` gocardless list creditors ``` ### Options ``` -h, --help help for creditors ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list customer_bank_accounts List customer bank accounts ### Synopsis This will fetch a list of customer bank accounts ``` gocardless list customer_bank_accounts [flags] ``` ### Examples ``` gocardless list customer_bank_accounts ``` ### Options ``` -h, --help help for customer_bank_accounts ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list customer_notifications List customer notifications ### Synopsis This will fetch a list of customer notifications ``` gocardless list customer_notifications [flags] ``` ### Examples ``` gocardless list customer_notifications ``` ### Options ``` -h, --help help for customer_notifications ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list customers List customers ### Synopsis This will fetch a list of customers ``` gocardless list customers [flags] ``` ### Examples ``` gocardless list customers ``` ### Options ``` -h, --help help for customers ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list events List events ### Synopsis This will fetch a list of events ``` gocardless list events [flags] ``` ### Examples ``` gocardless list events ``` ### Options ``` -h, --help help for events ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list mandate_imports List mandate imports ### Synopsis This will fetch a list of mandate imports ``` gocardless list mandate_imports [flags] ``` ### Examples ``` gocardless list mandate_imports ``` ### Options ``` -h, --help help for mandate_imports ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list mandates List mandates ### Synopsis This will fetch a list of mandates ``` gocardless list mandates [flags] ``` ### Examples ``` gocardless list mandates ``` ### Options ``` -h, --help help for mandates ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list payer_authorisations List payer authorisations ### Synopsis This will fetch a list of payer authorisations ``` gocardless list payer_authorisations [flags] ``` ### Examples ``` gocardless list payer_authorisations ``` ### Options ``` -h, --help help for payer_authorisations ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list payments List payments ### Synopsis This will fetch a list of payments ``` gocardless list payments [flags] ``` ### Examples ``` gocardless list payments ``` ### Options ``` -h, --help help for payments ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list payouts List payouts ### Synopsis This will fetch a list of payouts ``` gocardless list payouts [flags] ``` ### Examples ``` gocardless list payouts ``` ### Options ``` -h, --help help for payouts ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list refunds List refunds ### Synopsis This will fetch a list of refunds ``` gocardless list refunds [flags] ``` ### Examples ``` gocardless list refunds ``` ### Options ``` -h, --help help for refunds ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list subscriptions List subscriptions ### Synopsis This will fetch a list of subscriptions ``` gocardless list subscriptions [flags] ``` ### Examples ``` gocardless list subscriptions ``` ### Options ``` -h, --help help for subscriptions ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list webhooks List webhooks ### Synopsis This will fetch a list of webhooks ``` gocardless list webhooks [flags] ``` ### Examples ``` gocardless list webhooks ``` ### Options ``` -h, --help help for webhooks ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless list List resources by type ### Synopsis This will fetch a list of resources for the resource type specified ### Examples ``` gocardless list payments gocardless list customers gocardless list events ``` ### Options ``` -h, --help help for list ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless listen Listen for new webhooks ### Synopsis This will listen for any new webhooks, and either forward them onto a URL if one is provided, or print them onto the screen. ``` gocardless listen [flags] ``` ### Examples ``` # listen for events and print them to console gocardless listen # listen for events and forward them to a webhook url gocardless listen --forward "http://localhost:8001/webhook" ``` ### Options ``` -f, --forward string optional url to forward webhooks to -h, --help help for listen ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless login Login authorises a new merchants session ### Synopsis With the login command you can authorize directly against the GC CLI or authorize against an app that belongs to you if you are building a partner integration. You can fetch your App ID by selecting the app you choose to use from https://manage-sandbox.gocardless.com/partners/apps and copying the APP ID from the details ``` gocardless login [flags] ``` ### Examples ``` # authorise against the Gocardless CLI gocardless login # authorise against a partner app by providing the App ID gocardless login --app {APP_ID} ``` ### Options ``` -a, --app string App id to authorize merchant against -h, --help help for login ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless open Opens GoCardless web pages on browser ### Synopsis The open command acts as a shortcut to access GoCardless pages quickly in your browser. For example: To see all shortcuts available run 'gocardless open --list' ``` gocardless open [flags] ``` ### Examples ``` gocardless open --list gocardless open api gocardless open docs gocardless open customers gocardless open dashboard/webhooks ``` ### Options ``` -h, --help help for open --list List all supported short cuts ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless trigger billing_request_fulfilled_payment_failed Trigger a billing request fulfilled payment failed event ### Synopsis This will trigger a billing request fulfilled payment failed event ``` gocardless trigger billing_request_fulfilled_payment_failed [args] [flags] ``` ### Examples ``` gocardless trigger billing_request_fulfilled_payment_failed ``` ### Options ``` -h, --help help for billing_request_fulfilled_payment_failed ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger billing_request_fulfilled_payment_paid_out Trigger a billing request fulfilled payment paid out event ### Synopsis This will trigger a billing request fulfilled payment paid out event ``` gocardless trigger billing_request_fulfilled_payment_paid_out [args] [flags] ``` ### Examples ``` gocardless trigger billing_request_fulfilled_payment_paid_out ``` ### Options ``` -h, --help help for billing_request_fulfilled_payment_paid_out ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger billing_request_fulfilled Trigger a billing request fulfilled event ### Synopsis This will trigger a billing request fulfilled event ``` gocardless trigger billing_request_fulfilled [args] [flags] ``` ### Examples ``` gocardless trigger billing_request_fulfilled ``` ### Options ``` -h, --help help for billing_request_fulfilled ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger billing_request_pending Trigger a billing request pending event ### Synopsis This will trigger a billing request pending event ``` gocardless trigger billing_request_pending [args] [flags] ``` ### Examples ``` gocardless trigger billing_request_pending ``` ### Options ``` -h, --help help for billing_request_pending ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger mandate_activated Trigger a mandate activated event ### Synopsis This will trigger a mandate activated event ``` gocardless trigger mandate_activated [args] [flags] ``` ### Examples ``` gocardless trigger mandate_activated ``` ### Options ``` -h, --help help for mandate_activated ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger mandate_expired Trigger a mandate expired event ### Synopsis This will trigger a mandate expired event ``` gocardless trigger mandate_expired [args] [flags] ``` ### Examples ``` gocardless trigger mandate_expired ``` ### Options ``` -h, --help help for mandate_expired ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger mandate_failed Trigger a mandate failed event ### Synopsis This will trigger a mandate failed event ``` gocardless trigger mandate_failed [args] [flags] ``` ### Examples ``` gocardless trigger mandate_failed ``` ### Options ``` -h, --help help for mandate_failed ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger mandate_pending_submission Trigger a mandate pending submission event ### Synopsis This will trigger a mandate pending submission event ``` gocardless trigger mandate_pending_submission [args] [flags] ``` ### Examples ``` gocardless trigger mandate_pending_submission ``` ### Options ``` -h, --help help for mandate_pending_submission ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger mandate_transferred Trigger a mandate transferred event ### Synopsis This will trigger a mandate transferred event ``` gocardless trigger mandate_transferred [args] [flags] ``` ### Examples ``` gocardless trigger mandate_transferred ``` ### Options ``` -h, --help help for mandate_transferred ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger payment_chargeback_settled Trigger a payment chargeback settled event ### Synopsis This will trigger a payment chargeback settled event ``` gocardless trigger payment_chargeback_settled [args] [flags] ``` ### Examples ``` gocardless trigger payment_chargeback_settled ``` ### Options ``` -h, --help help for payment_chargeback_settled ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger payment_charged_back Trigger a payment charged back event ### Synopsis This will trigger a payment charged back event ``` gocardless trigger payment_charged_back [args] [flags] ``` ### Examples ``` gocardless trigger payment_charged_back ``` ### Options ``` -h, --help help for payment_charged_back ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger payment_confirmed Trigger a payment confirmed event ### Synopsis This will trigger a payment confirmed event ``` gocardless trigger payment_confirmed [args] [flags] ``` ### Examples ``` gocardless trigger payment_confirmed ``` ### Options ``` -h, --help help for payment_confirmed ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger payment_failed Trigger a payment failed event ### Synopsis This will trigger a payment failed event ``` gocardless trigger payment_failed [args] [flags] ``` ### Examples ``` gocardless trigger payment_failed ``` ### Options ``` -h, --help help for payment_failed ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger payment_paid_out Trigger a payment paid out event ### Synopsis This will trigger a payment paid out event ``` gocardless trigger payment_paid_out [args] [flags] ``` ### Examples ``` gocardless trigger payment_paid_out ``` ### Options ``` -h, --help help for payment_paid_out ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger payment_pending_submission Trigger a payment pending submission event ### Synopsis This will trigger a payment pending submission event ``` gocardless trigger payment_pending_submission [args] [flags] ``` ### Examples ``` gocardless trigger payment_pending_submission ``` ### Options ``` -h, --help help for payment_pending_submission ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger payment_submitted Trigger a payment submitted event ### Synopsis This will trigger a payment submitted event ``` gocardless trigger payment_submitted [args] [flags] ``` ### Examples ``` gocardless trigger payment_submitted ``` ### Options ``` -h, --help help for payment_submitted ``` ### Options inherited from parent commands ``` --billing_request string A billing request resource --config string config file (default is $HOME/.gc-cli/config.json) --customer string A customer resource --mandate string A mandate resource --payment string A payment resource ``` --- ## gocardless trigger Trigger an event ### Synopsis Trigger a specific event. Events triggered with this command will create all othernecessary webhooks and objects required to successfully create the triggered event. You can provide a resource id along with this event if you choose to limit how many objects are autogenerated. This way the provided resource can be used in the trigger process without a new one having to be created ### Examples ``` # trigger a mandate_activated event without params - this autogenerates all objects required for mandate activation gocardless trigger mandate_activated # trigger a mandate activated event with a customer id - this triggers a mandate activated event for the specified customer gocardless trigger mandate_activated customer=customer_id # trigger a payment_confirmed event with a mandate id - this triggers a payment confirmed event for the specified mandate gocardless trigger payment_confirmed mandate=MA00192829 ``` ### Options ``` --billing_request string A billing request resource --customer string A customer resource -h, --help help for trigger --mandate string A mandate resource --payment string A payment resource ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless update updates the requested resource ### Synopsis This will call the update api for the requested resource and updates it in GoCardless This command uses the `--data` (or `-d`) flag to construct the data payload for the request. Otherwise you can use `--editorName vim`, then you can enter json and exit to submit. See a list of possible resources from the GoCardless API Reference: /docs/api-reference#core-endpoints ``` gocardless update {resource} {resource_id} [flags] ``` ### Examples ``` # update a subscription's name. gocardless update subscription SB1234 -d name=SUB # update a subscription with editor # opens vim prompt and then you can enter json data. gocardless update subscription SB1234 --editorName vim ``` ### Options ``` -d, --data stringArray Data for the API request --editorName string Pass an editor to read data from. -h, --help help for update ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` --- ## gocardless version Print version of CLI ``` gocardless version [flags] ``` ### Examples ``` gocardless version ``` ### Options ``` -h, --help help for version ``` ### Options inherited from parent commands ``` --config string config file (default is $HOME/.gc-cli/config.json) ``` ## MCP Terms and Conditions (Live Access) URL: https://docs.gocardless.com/docs/developer-resources/mcp/terms > Legal terms for use of the GoCardless Model Context Protocol (MCP) server (Live Access) # MCP Terms and Conditions (Live Access) GoCardless Limited is a company registered in England and Wales with company number 07495895 and registered office at Sutton Yard, 65 Goswell Road, London, England, EC1V 7EN (**"GoCardless", "our", "us, "we"**). 1. **UNDERSTANDING THESE TERMS** 1. In these Terms (as defined below), when we refer to "**we**", "**us**" or "**our**", we mean GoCardless and when we refer to "**you**" or "**your**" we mean any person that accesses or uses the CLI, MCP, MCP Data and/or the MCP Services. 2. These terms of use (these "**Terms**") set out the basis upon which you may make use of our command line interface software tool ("**CLI**") and our model context protocol software tool ("**MCP**") following the successful completion of the Configuration Process (as defined below) in accordance with these Terms, are made available to the Configured AI Tool (as defined below) in response to an Input (as defined below) via the MCP ("**MCP Data**"). 3. These Terms set out your rights and obligations when accessing or using the CLI, MCP, MCP Data and/or the MCP Services (as defined below). 4. By accessing or using the CLI, MCP, MCP Data and/or the MCP Services (as applicable) you agree to be bound by these Terms. If you do not wish to be bound by these Terms you should not access or use the CLI, MCP, MCP Data and/or the MCP Services (as applicable). 5. When certain words and phrases are used in these Terms, they have specified meanings (these are known as "**defined terms**"). You can identify these defined terms because they start with capital letters (even if they are not at the start of the sentence). When a defined term is used, it has the meaning given to it in the section of these Terms where it was defined (you can find these meanings by looking at the sentence where the defined term is included in brackets and speech marks). We also define other words which are referenced in bold in the paragraphs set out below. 6. In the event of a conflict between these Terms and the terms of any merchant agreement entered into between you and GoCardless ("**Merchant Agreement**"), the terms of the Merchant Agreement will prevail to the extent of the conflict. 2. **PROVISION OF THE CLI, MCP, MCP DATA AND/OR THE MCP SERVICES** 1. In order to be able to receive the MCP Services you must complete the following set-up process: 1. download a copy of the [CLI and MCP](/docs/developer-resources/mcp) onto your systems ("**Customer Systems"**), or connect directly to the to the remote hosted MCP; 2. if you are connecting via the CLI, once the CLI and MCP have been downloaded onto the Customer Systems, you must complete the relevant configuration process which can be found here: [Tools: GC CLI \- GoCardless Developers](/docs/developer-resources/gc-cli) and here: [GC MCP](/docs/developer-resources/mcp) so that your chosen AI tool can be successfully configured with the MCP (such chosen AI tool that has been successfully configured with the MCP being, the "**Configured AI Tool"**) so that the MCP and Configured AI Tool can communicate effectively with each other (the **"Configuration Process"**). For the avoidance of doubt, unless the context otherwise requires, all references to "MCP" in these Terms (when used in the context of the MCP communicating with the Configured AI Tool following the successful completion of the Configuration Process) shall mean the MCP downloaded onto the Customer Systems and in respect of which the Configuration Process has been successfully completed or to which you have connected directly to the remote hosted MCP (as the case may be); and 3. in order to connect with the MCP (including where you connect via the CLI), you must authenticate via OAuth. 2. Following the successful completion of the Configuration Process and subject to these Terms, GoCardless grants you or the AI Service Provider (as defined below) a right to be able to send Inputs to the MCP via the Configured AI Tool in order to receive the relevant MCP Data (**"MCP Services"**). 3. The CLI, MCP and MCP Data are provided free of charge. GoCardless reserves the right to charge in the future. 4. We aim to keep the CLI and MCP available and functioning at all times. However, access and use may be limited due to maintenance, updates, or technical issues, and we do not guarantee continuous, uninterrupted availability. We reserve the right to suspend, modify, withdraw, or change any part of the CLI, MCP, MCP Data, and/or MCP Services (as applicable) without notice, or in accordance with applicable law. You may need to reconfigure the system if such changes occur. We will not be liable for any unavailability or disruptions beyond our control, except as required by law. We may update the CLI, MCP, or associated services at any time. 3. **GENERAL** 1. You are responsible for ensuring that you have and maintain all the hardware and software necessary, including the Customer Systems, to use the CLI and MCP so that you can receive the MCP Services. 2. You are solely responsible for successfully completing the Configuration Process in accordance with these Terms so that you can receive the MCP Services. 3. The CLI, MCP, MCP Data, and/or MCP Services (as applicable) are provided strictly for general informational purposes only. They are not intended to constitute, nor should they be relied upon as, professional advice or recommendations. We expressly disclaim any reliance on the accuracy, completeness, or suitability of the information provided, and make no representations or warranties regarding their use for any specific purpose. 4. We do not guarantee that the CLI, MCP or MCP Data (as applicable) will be secure, or free from bugs or viruses. 4. **ACCEPTABLE USE** 1. You agree: 1. that you are solely permitted to enable your AI Service Provider to receive the MCP Data on your behalf and incorporate such MCP Data into any Output; 2. to co-operate with GoCardless in all matters relating to the CLI, MCP, MCP Data and/or MCP Services (as applicable); 3. to implement and maintain appropriate technical and organisational measures to protect MCP Data against unauthorised access, alteration, disclosure, or destruction. In the event of a data breach affecting MCP Data, you shall promptly notify us within 48 hours of becoming aware of the breach. 4. not to use the CLI, MCP, MCP Data and/or the MCP Services (as applicable) in any way that breaches these Terms or any applicable local, national or international law or regulation; 5. not to use the CLI, MCP, MCP Data and/or the MCP Services (as applicable) to process or handle any personal data; 6. not to infringe our intellectual property rights or those of any third party in relation to your use of the CLI, MCP, MCP Data and/or MCP Services (as applicable); 7. not to misuse the CLI or MCP (as applicable) by introducing viruses, trojans, worms, logic bombs, or other material which is malicious or technologically harmful into the CLI or MCP (as applicable); 8. except to the extent permitted by law, not to modify, decompile or reverse engineer any software or the source code of the underlying software supplied as part of, or in connection with, the CLI or MCP (as applicable); 9. not to "frame" or "mirror" any part of the CLI or MCP (as applicable) without our prior written consent; 10. not use the CLI, MCP, MCP Data and/or the MCP Services (as applicable) for any other purposes other than those expressly set out in these Terms; 11. not to execute any form of network monitoring or run a network analyser or packet sniffer or other technology to intercept, decode, mine or display any packets used to communicate between or with the servers of the CLI and MCP (as applicable); 12. not to copy or otherwise reproduce or re-sell any part of the CLI, MCP, MCP Data and/or MCP Services (as applicable) unless expressly permitted to do so under these Terms; 13. save to the extent expressly permitted under these Terms, not to rent, lease, sub-licence, loan, translate, merge, adapt, vary or modify the CLI, MCP, MCP Data and/ or MCP Services (as applicable); 14. not to make alterations or modifications of, the whole or part of any of the CLI, MCP, MCP Data and or MCP Services (as applicable), or permit the CLI, MCP, MCP Data and/or MCP Services (as applicable) or any part of them to be combined with, or become incorporated into, other programs unless as expressly permitted to do so under these Terms; 15. not to circumvent any technical measures we use to provide and/or secure the CLI or MCP (as applicable); 16. not to attempt to gain unauthorised access to our computer systems or engage activity that disrupts, diminishes the quality of, interferes with the performance of, or impairs the functionality of the CLI, MCP and/or MCP Data, including to receive the MCP Services (as applicable); 17. not to copy, archive, store, reproduce, rearrange, modify, download, upload, create derivative works from, display, perform, publish, distribute, redistribute or disseminate all or any part of the CLI, MCP, MCP Data and/or MCP Services unless as expressly permitted pursuant to these Terms; 18. not to access the CLI, MCP, MCP Data and/or the MCP Services (as applicable) for the purpose of building a product using similar ideas, functions, features, interface or graphics as those found in the CLI, MCP, MCP Data and/or the MCP Services (as applicable); 19. to hold any necessary licences, certifications and/or qualifications that are required to access and use the CLI, MCP, MCP Data and/or MCP Services; and 20. not to access the CLI or MCP to upload any content or computer code for the purposes of: a) causing a breach or override of security to the CLI or MCP; b) interfering with the proper working, functionality or performance of the CLI and/or MCP including to receive the MCP Data and/or MCP Services (as applicable); and/or c) preventing others from accessing or using the CLI, MCP, MCP Data and/or the MCP Services (as applicable); and 21. to keep confidential and protect against unauthorised access or disclosure all MCP Data. 2. You shall procure that the AI Service Provider represents, undertakes and warrants that: 1. it shall use the MCP Data solely for the purposes of incorporating it into the relevant Output; 2. it shall not use the MCP Data for any purposes (other than those described in paragraph 4.2.1 above) including to improve or train any of its AI tools or models (including the Configured AI Tool) or for any other ancillary services; 3. It shall ensure that, during and after processing, MCP Data remains confidential and protected against unauthorised access or disclosure; and 4. once the AI Service Provider has received the MCP Data and incorporated it into the relevant Output, the AI Service Provider will immediately delete and destroy any MCP Data from its servers and systems (and certify that it has done so), and it further acknowledges and agrees to not use the MCP Data for any further purposes. 3. You shall be responsible for any failure by the AI Service Provider to keep the MCP Data confidential and protected against unauthorised access and disclosure. 5. **THIRD PARTY APPLICATIONS** 1. The MCP integrates and communicates with the Configured AI Tool. You acknowledge and agree that any Configured AI Tool is not under GoCardless' control (and for the avoidance of doubt, is subject to the terms and conditions between you and the relevant AI Service Provider), and you further acknowledge and agree that GoCardless is not responsible or liable for any Configured AI Tool, including any Inputs or Outputs. 2. The inclusion or integration with any Configured AI Tool does not imply endorsement by GoCardless of that Configured AI Tool. 3. You further acknowledge and agree that GoCardless will not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with use or reliance on any Configured AI Tool, including the provision of any Outputs. Use of any Configured AI Tool and the Outputs created is solely at your own risk. 6. **INTELLECTUAL PROPERTY** 1. We are the owner or the licensee (as applicable) of all intellectual property rights subsisting in the CLI, MCP and/or MCP Data. Those works are protected by copyright laws and treaties around the world. All such rights are reserved. 2. You are not granted any right to use, and may not use, any of our intellectual property rights other than as set out in these Terms. 3. Subject to your compliance with these Terms, we grant you a non-transferable, non-sublicensable, non-exclusive, revocable, worldwide, royalty free and fully paid-up limited licence to copy and download the CLI and MCP onto the Customer Systems solely for the purposes of accessing the CLI and MCP to complete the Configuration Process. 4. Subject to your compliance with these Terms and following the successful completion of the Configuration Process, we grant you a non-transferable, non-sublicensable, non-exclusive, revocable, worldwide, royalty free and fully paid-up limited licence to use, and, subject to paragraph 4.2.4, for the AI Service Provider to use the MCP Data solely for the purposes of incorporating the relevant MCP Data into the relevant Output. 5. We may revoke or terminate the licences described in paragraphs 6.3 and 6.4 if you: (i) breach these Terms; or (ii) at our discretion without notice or liability. 6. Where any MCP Data is incorporated into the relevant Output ("**Incorporated MCP Data"**), all intellectual property rights subsisting in such Incorporated MCP Data will be retained by GoCardless, and the terms of paragraph 6.7 shall apply. 7. Subject to your compliance with these Terms, we grant you a non-transferable, non-sublicensable, non-exclusive, irrevocable, worldwide, royalty free and fully paid-up perpetual licence to use the Incorporated MCP Data in order to be able to use the relevant Output. 8. You grant to GoCardless a perpetual, worldwide, non-exclusive, royalty-free licence to use, copy, record, distribute, reproduce, disclose, sell, re-sell, sublicence, display, publicly perform, transmit, publish, broadcast, translate, make derivative works, and otherwise use and exploit in any manner whatsoever, all or any portion of any Inputs or Outputs (including any derivative works thereof) for any business purposes. 9. You acknowledge and agree that GoCardless and its licensors shall have a royalty-free, worldwide, transferable, sub-licensable, irrevocable, perpetual licence to use or incorporate into the CLI, MCP and/or MCP Data any enhancement requests or feedback provided by you, so long as you are not identified in any way as the source of such feedback. For the avoidance of doubt, GoCardless shall not be obliged to implement any such enhancement requires or feedback 7. **WARRANTIES** 1. You warrant and undertake that: 1. you are free to enter into these Terms and to perform the obligations imposed on you hereunder; 2. you shall comply with these Terms and all applicable law in relation to the exercise of your rights and fulfilment of your obligations under these Terms; 3. you own, or have a licence to use all rights (including intellectual property rights) in the Inputs and Outputs; 4. the use by us of any Inputs and Outputs in accordance with these Terms shall not infringe the rights, including the intellectual property rights, of any third-party; and 5. you shall not use the MCP Data made available via the MCP for any Prohibited AI Practices or in connection with any High-Risk Systems. 2. The CLI, MCP, MCP Data and/or any MCP Services (as applicable) received by you (including, for the avoidance of doubt, any Outputs) are provided on an "as is" basis. The express terms and conditions of these Terms will apply in place of all warranties, conditions, terms, representations, statements, undertakings and obligations implied by statute, common law, custom, trade usage or otherwise (including implied undertakings of satisfactory quality and fitness for purpose), all of which are excluded to the fullest extent permitted by law. 3. We do not warrant or guarantee that the CLI, MCP, MCP Data and/or any MCP Services received by you (including, for the avoidance of doubt, any Outputs) (as applicable) are correct, accurate, reliable, error-free, or free from any bias or hallucinations. 8. **DATA PROTECTION** 1. In this paragraph 8: 1. the terms "**Data Controller**", "**Data Subject**", "**Personal Data**", "**Personal Data Breach**" and "**Process**" have the meanings given in the GDPR; 2. "**Data Protection Law**" means the laws, regulations or adopted codes of practice applicable to any Service relating to data protection, privacy, security or electronic communications. This may include the GDPR or an applicable local equivalent; 3. "**GDPR**" means the General Data Protection Regulation (EU) 2016/679; and 4. "**Regulatory Authority**" means any person or body concerned with the creation, enforcement or supervision of, making or compliance with, Data Protection Law and having jurisdiction over GoCardless or you (as applicable). 2. You and GoCardless act as independent Data Controllers, or the equivalent under Data Protection Law in relation to any Personal Data that you or GoCardless is Process in the course of the performance of these Terms. The parties shall comply with their respective obligations under Data Protection Law for the duration of these Terms. 3. Each party shall not knowingly perform its obligations under these Terms in such a way as to cause the other party to breach any of its obligations under Data Protection Law. Neither party shall be responsible for any consequences resulting from the other party's failure to comply with Data Protection Law in relation to Personal Data that it shares with the other party. 4. Each party agrees that it will: (a) ensure appropriate technical and organisational security measures are in place to protect Personal Data under its control; (b) transfer Personal Data between jurisdictions only where it has taken appropriate measures to make the transfer lawful under Data Protection Law; (c) notify the other party without undue delay if it receives a request, complaint or other communication from a Data Subject or a Regulatory Authority that is addressed to or intended for the other party, and provide reasonable assistance where required unless prevented from doing so by Applicable Law; (d) notify the other party without undue delay if it is required to notify a Regulatory Authority or data subject under Data Protection Law of any Personal Data Breach in relation to Personal Data processed under this Agreement; and (e) provide such information as may reasonably be requested by the other party from time to time concerning the measures that party has taken to ensure compliance with its obligations under these Terms and Data Protection Law. 9. **LIABILITY** 1. Nothing in these Terms excludes or limits our or your liability for: 1. death or personal injury caused by our negligence; 2. wilful default or wilful misconduct; 3. fraud or fraudulent misrepresentation; 4. any other liability that cannot be excluded or limited by applicable law. 2. Your liability in respect of the indemnity in paragraph 9.6 is unlimited (and, accordingly, all limitations set out in this paragraph 9 will not apply to such liability). 3. We are not liable to you for any loss or damage, whether in contract, tort (including negligence), breach of statutory duty, or otherwise, even if foreseeable, arising under or in connection with: 1. your use of, or inability to use, the CLI, MCP, MCP Data and/or any Services (as applicable); or 2. your use of or reliance on any MCP Data or Outputs accessed through the MCP. 4. Subject to paragraph 9.1, and to the extent permitted under applicable law in no event shall we be liable to you for: 1. any loss of profits, loss of revenue, loss of corrupted data, damage to goodwill, loss of contracts, failure to realise anticipated savings (in each case, where arising directly or indirectly); or 2. any indirect or consequential loss or damage. 5. Subject to paragraph 9.1, our total aggregate liability, whether in contract, tort (including negligence and breach of statutory duty, howsoever arising), misrepresentation (whether negligent or innocent), restitution or otherwise, arising under or in connection with these Terms shall be limited to £50. 6. You agree to indemnify, defend, and hold harmless GoCardless and its affiliates, officers, directors, and employees (together the "**Indemnified Parties**"),in respect of any demand, loss, damage, cost, expense or liability (including all legal and other professional costs on a full indemnity basis) suffered or incurred by the Indemnified Parties as a result of: (i) any breach of these Terms; (ii) your misuse of the CLI, MCP, MCP Data and/or MCP Services (as applicable); (iii) any claim that the Inputs and Outputs infringes any rights of a third-party (including any intellectual property rights); (iv) any claims made by any third parties in respect of the CLI, MCP, MCP Data and/or MCP Services (as applicable); and( v) any claim made by any third party relating or arising out of processing of personal data. 7. GoCardless reserves the right, at your expense, to assume the exclusive defence and control of any matter for which you are required to indemnify the Indemnified Parties, and you agree to cooperate with GoCardless in defence of these claims. You agree not to settle any matter without the prior written consent of GoCardless. GoCardless will use reasonable efforts to notify you of any such claims upon becoming aware of it. 10. **TERMINATION** 1. GoCardless may terminate these Terms for convenience at any time In the event of termination by GoCardless pursuant to this paragraph 10.1, GoCardless shall have no further liability to you. 2. If you breach any of these Terms, we may immediately do any or all of the following (without limitation): 1. issue a warning to you; 2. issue legal proceedings against you for reimbursement of all costs resulting from the breach (including, but not limited to, reasonable administrative and legal costs); 3. take further legal action against you; and/or 4. disclose such information to law enforcement authorities as we reasonably feel is necessary to do so. 3. These Terms shall automatically terminate where GoCardless exercises its termination rights pursuant to these Terms. 4. We may terminate your access to or use of the CLI, MCP, MCP Data and/or Services (as applicable), or the AI Service Providers access to the MCP Data, immediately upon notice, if we determine, acting reasonably,without incurring liability to you: 1. that your use or access of the CLI, MCP, MCP Data and/or MCP Services: (a) poses a security risk to GoCardless, the CLI, MCP or MCP Data or any third party; (b) may adversely impact the availability or performance of the MCP, MCP Data or your ability to receive the MCP Services, or the systems or software of any other customer of GoCardless; (c) may subject us or any third party to any liability; or (d) may be fraudulent; or 2. that you are in breach of these Terms or any other agreement (including any agreement with the AI Service Provider in respect of your use of the Configured AI Tool). 5. On termination of these Terms for any reason: 1. subject to paragraph 6.7, you will not (and you will procure the AI Service Provider will not, as applicable) be permitted to use the MCP, MCP Data and/or MCP Services (as applicable), and you shall stop using the MCP, MCP Data and/or MCP Services (as applicable) immediately; 2. subject to paragraphs 6.7, 6.8 and 6.9, all licences granted under these Terms shall immediately terminate and you shall immediately cease all use of the MCP, MCP Data and/or MCP Services (as applicable). For the avoidance of doubt, any licences granted on a perpetual and irrevocable basis shall survive the termination of these Terms for any reason and shall continue in full force and effect; 3. you must immediately delete all copies of the CLI and MCP from the Customer Systems; 4. any rights, remedies, obligations or liabilities of the parties that have accrued up to the date of termination, including the right to claim damages in respect of any breach of these Terms which existed at or before the date of termination shall not be affected or prejudiced; and 5. the provisions of these Terms which by their nature should survive suspension or termination will survive. 11. **CHANGES TO THESE TERMS** 1. We may make changes to these Terms from time to time. Please check these Terms regularly to ensure that you understand the Terms that apply at the time that you access and use the MCP and MCP Data including to receive the MCP Services. **OTHER IMPORTANT INFORMATION** 2. Force Majeure. We shall not be in breach of these Terms nor liable for delay in performing, or failure to perform, any of our obligations under these Terms if such delay or failure results from events, circumstances or causes beyond our reasonable control, including, without limitation, strikes, lock-outs or other industrial disputes (whether involving our workforce or any other party), failure of a utility service or transport or telecommunications network or the internet, act of God, war, riot, civil commotion, malicious damage, compliance with any law or governmental order, rule, regulation or direction, accident, breakdown of plant or machinery, fire, flood, storm or default of suppliers or sub-contractors. In such circumstances we shall be entitled to a reasonable extension of the time for performing such obligations. 3. Entire Agreement. These Terms are the entire agreement between us related to the subject matter in these Terms. These Terms replace and supersede any other prior or contemporaneous agreement, representation or discussion, oral or written. 4. No Waiver. The failure to exercise, or delay in exercising, a right, power or remedy provided by these Terms or by law shall not constitute a waiver of that right, power or remedy. If a party waives a breach of any provision of these Terms, this shall not operate as a waiver of a subsequent breach of that provision, or as a waiver of a breach of any other provision. 5. Rights and Remedies. Except as expressly provided in these Terms, the rights and remedies provided under these Terms, are in addition to, and not exclusive of, any rights or remedies provided by law. 6. Severance. If any provision, or part of a provision, of these Terms is found by any court or authority of competent jurisdiction to be illegal, invalid or unenforceable, that provision or part-provision shall be deemed not to form part of these Terms, and the legality, validity or enforceability of the remainder of the provisions of these Terms shall not be affected, unless otherwise required by operation of applicable law. If any invalid, unenforceable or illegal provision would be valid, enforceable or legal if some part of it were modified, the provision shall apply with whatever modification is necessary to give effect to the commercial intention of the parties. 7. Assignment. You shall not, without the prior written consent of us assign, transfer, charge, sub-contract or deal in any other manner with all or any of its rights or obligations under these Terms. We may, at any time, assign, transfer, charge, sub-contract or deal in any other manner with all or any of its rights or obligations under these Terms. You shall enter into any further agreements reasonably required by us to give effect to any of the above. 8. Relationship of the Parties. Nothing in these Terms are intended to, or shall be deemed to, establish or constitute any partnership or joint venture between any of the parties, create a relationship of principal and agent for any purpose between the parties, or authorise either party to make or enter into any commitments for or on behalf of the other party. 9. Notices. Where we need to send you notices under these Terms or in connection with your use of the CLI, MCP, MCP Data and/or Services (as applicable), you acknowledge and agree to receive emails from us. All notices in relation to legal proceedings must be sent to legalnotices@gocardless.com. 10. For the purposes of these Terms, the following definitions will apply: 1. **"AI Service Provider"** means the service provider of the Configured AI Tool, and which you have entered into a separate agreement with so that you can access and use the Configured AI Tool; 2. **"EU AI Act"** means Regulation (EU) 2024/1689; 3. "**High Risk System**" means any AI system (or any part thereof) which is considered to be high-risk under the EU AI Act (cf. Art. 6 (1)-(3) EU AI Act); 4. **"Inputs"** means, following the successful completion of the Configuration Process in accordance with these Terms, any natural language prompt or other material, information or data inputted into the Configured AI Tool by you (or the AI Service Provider) and sent to the MCP in order to generate an Outputs; 5. "**Outputs**" means, following the successful completion of the Configuration Process in accordance with these Terms, any documentation, code, information, data, content, materials, and any other outputs generated by the Configured AI Tool in response to an Input and which includes MCP Data; 6. **"Prohibited AI Practices"** means the prohibited AI activities as defined in Article 5 of the EU AI Act or under any other applicable law. 12. **GOVERNING LAW AND JURISDICTION** 1. These terms and any dispute or claim arising out of or in connection with them or their subject matter or formation (including non-contractual disputes or claims) shall be governed by and construed in accordance with the law of England and Wales and you and we irrevocably agree that the courts of England and Wales shall have exclusive jurisdiction to settle any dispute or claim arising out of or in connection with these terms or their subject matter or formation (including non-contractual disputes or claims). Terms last updated 20 April 2026\. ## What's Next? #### [GC MCP](/docs/developer-resources/mcp) The GoCardless MCP enables you interact with GC's API via AI surfaces. ## MCP Terms and Conditions (Sandbox Access) URL: https://docs.gocardless.com/docs/developer-resources/mcp/terms-sandbox > Legal terms for use of the GoCardless Model Context Protocol (MCP) server (Sandbox Access) # MCP Terms and Conditions (Sandbox Access) GoCardless Limited is a company registered in England and Wales with company number 07495895 and registered office at Sutton Yard, 65 Goswell Road, London, England, EC1V 7EN (**"GoCardless", "our", "us, "we"**). 1. **UNDERSTANDING THESE TERMS** 1. In these Terms (as defined below), when we refer to "**we**", "**us**" or "**our**", we mean GoCardless and when we refer to "**you**" or "**your**" we mean any person that accesses or uses the CLI, MCP, MCP Data and/or the MCP Services. 2. These terms of use (these "**Terms**") set out the basis upon which you may make use of our command line interface software tool ("**CLI**") and our model context protocol software tool ("**MCP**") following the successful completion of the Configuration Process (as defined below) in accordance with these Terms, are made available to the Configured AI Tool (as defined below) in response to an Input (as defined below) via the MCP ("**MCP Data**"). 3. These Terms set out your rights and obligations when accessing or using the CLI, MCP, MCP Data and/or the MCP Services (as defined below). 4. By accessing or using the CLI, MCP, MCP Data and/or the MCP Services (as applicable) you agree to be bound by these Terms. If you do not wish to be bound by these Terms you should not access or use the CLI, MCP, MCP Data and/or the MCP Services (as applicable). 5. When certain words and phrases are used in these Terms, they have specified meanings (these are known as "**defined terms**"). You can identify these defined terms because they start with capital letters (even if they are not at the start of the sentence). When a defined term is used, it has the meaning given to it in the section of these Terms where it was defined (you can find these meanings by looking at the sentence where the defined term is included in brackets and speech marks). We also define other words which are referenced in bold in the paragraphs set out below. 2. **PROVISION OF THE CLI, MCP, MCP DATA AND/OR THE MCP SERVICES** 1. In order to be able to receive the MCP Services you must complete the following set-up process: 1. download a copy of the [CLI](/docs/developer-resources/gc-cli) and [MCP](/docs/developer-resources/mcp) onto your systems ("**Customer Systems"**), or connect directly to the to the remote hosted MCP; and 2. If you are connecting via the CLI, once the CLI and MCP have been downloaded onto the Customer Systems, you must complete the relevant configuration process which can be found here: [Tools: GC CLI \- GoCardless Developers](/docs/developer-resources/gc-cli) and here: [MCP](/docs/developer-resources/mcp) so that your chosen AI tool can be successfully configured with the MCP (such chosen AI tool that has been successfully configured with the MCP being, the "**Configured AI Tool"**) so that the MCP and Configured AI Tool can communicate effectively with each other (the **"Configuration Process"**). For the avoidance of doubt, unless the context otherwise requires, all references to "MCP" in these Terms (when used in the context of the MCP communicating with the Configured AI Tool following the successful completion of the Configuration Process) shall mean the MCP downloaded onto the Customer Systems and in respect of which the Configuration Process has been successfully completed or to which you have connected directly to the remote hosted MCP (as the case may be). 2. Following the successful completion of the Configuration Process and subject to these Terms, GoCardless grants you or the AI Service Provider (as defined below) a right to be able to send Inputs to the MCP via the Configured AI Tool in order to receive the relevant MCP Data (**"MCP Services"**). 3. The CLI, MCP and MCP Data are provided free of charge. GoCardless reserves the right to charge in the future. 4. We aim to keep the CLI and MCP available and functioning at all times. However, access and use may be limited due to maintenance, updates, or technical issues, and we do not guarantee continuous, uninterrupted availability. We reserve the right to suspend, modify, withdraw, or change any part of the CLI, MCP, MCP Data, and/or MCP Services (as applicable) without notice, or in accordance with applicable law. You may need to reconfigure the system if such changes occur. We will not be liable for any unavailability or disruptions beyond our control, except as required by law. We may update the CLI, MCP, or associated services at any time. 3. **GENERAL** 1. You are responsible for ensuring that you have and maintain all the hardware and software necessary, including the Customer Systems, to use the CLI and MCP so that you can receive the MCP Services. 2. You are solely responsible for successfully completing the Configuration Process in accordance with these Terms so that you can receive the MCP Services. 3. The CLI, MCP, MCP Data, and/or MCP Services (as applicable) are provided strictly for general informational purposes only. They are not intended to constitute, nor should they be relied upon as, professional advice or recommendations. We expressly disclaim any reliance on the accuracy, completeness, or suitability of the information provided, and make no representations or warranties regarding their use for any specific purpose. 4. We do not guarantee that the CLI, MCP or MCP Data (as applicable) will be secure, or free from bugs or viruses. 4. **ACCEPTABLE USE** 1. You agree: 1. that you are solely permitted to enable your AI Service Provider to receive the MCP Data on your behalf and incorporate such MCP Data into any Output; 2. to co-operate with GoCardless in all matters relating to the CLI, MCP, MCP Data and/or MCP Services (as applicable); 3. to implement and maintain appropriate technical and organisational measures to protect MCP Data against unauthorised access, alteration, disclosure, or destruction. In the event of a data breach affecting MCP Data, you shall promptly notify us within 48 hours of becoming aware of the breach. 4. not to use the CLI, MCP, MCP Data and/or the MCP Services (as applicable) in any way that breaches these Terms or any applicable local, national or international law or regulation; 5. not to use the CLI, MCP, MCP Data and/or the MCP Services (as applicable) to process or handle any personal data; 6. not to infringe our intellectual property rights or those of any third party in relation to your use of the CLI, MCP, MCP Data and/or MCP Services (as applicable); 7. not to misuse the CLI or MCP (as applicable) by introducing viruses, trojans, worms, logic bombs, or other material which is malicious or technologically harmful into the CLI or MCP (as applicable); 8. except to the extent permitted by law, not to modify, decompile or reverse engineer any software or the source code of the underlying software supplied as part of, or in connection with, the CLI or MCP (as applicable); 9. not to "frame" or "mirror" any part of the CLI or MCP (as applicable) without our prior written consent; 10. not use the CLI, MCP, MCP Data and/or the MCP Services (as applicable) for any other purposes other than those expressly set out in these Terms; 11. not to execute any form of network monitoring or run a network analyser or packet sniffer or other technology to intercept, decode, mine or display any packets used to communicate between or with the servers of the CLI and MCP (as applicable); 12. not to copy or otherwise reproduce or re-sell any part of the CLI, MCP, MCP Data and/or MCP Services (as applicable) unless expressly permitted to do so under these Terms; 13. save to the extent expressly permitted under these Terms, not to rent, lease, sub-licence, loan, translate, merge, adapt, vary or modify the CLI, MCP, MCP Data and/ or MCP Services (as applicable); 14. not to make alterations or modifications of, the whole or part of any of the CLI, MCP, MCP Data and or MCP Services (as applicable), or permit the CLI, MCP, MCP Data and/or MCP Services (as applicable) or any part of them to be combined with, or become incorporated into, other programs unless as expressly permitted to do so under these Terms; 15. not to circumvent any technical measures we use to provide and/or secure the CLI or MCP (as applicable); 16. not to attempt to gain unauthorised access to our computer systems or engage activity that disrupts, diminishes the quality of, interferes with the performance of, or impairs the functionality of the CLI, MCP and/or MCP Data, including to receive the MCP Services (as applicable); 17. not to copy, archive, store, reproduce, rearrange, modify, download, upload, create derivative works from, display, perform, publish, distribute, redistribute or disseminate all or any part of the CLI, MCP, MCP Data and/or MCP Services unless as expressly permitted pursuant to these Terms; 18. not to access the CLI, MCP, MCP Data and/or the MCP Services (as applicable) for the purpose of building a product using similar ideas, functions, features, interface or graphics as those found in the CLI, MCP, MCP Data and/or the MCP Services (as applicable); 19. to hold any necessary licences, certifications and/or qualifications that are required to access and use the CLI, MCP, MCP Data and/or MCP Services; and 20. not to access the CLI or MCP to upload any content or computer code for the purposes of: 1) causing a breach or override of security to the CLI or MCP; 2) interfering with the proper working, functionality or performance of the CLI and/or MCP including to receive the MCP Data and/or MCP Services (as applicable); and/or 3) preventing others from accessing or using the CLI, MCP, MCP Data and/or the MCP Services (as applicable). 2. You shall procure that the AI Service Provider represents, undertakes and warrants that: 1. it shall use the MCP Data solely for the purposes of incorporating it into the relevant Output; 2. it shall not use the MCP Data for any purposes (other than those described in paragraph 4.2.1 above) including to improve or train any of its AI tools or models (including the Configured AI Tool) or for any other ancillary services; 3. It shall ensure that, during and after processing, MCP Data remains confidential and protected against unauthorised access or disclosure; and 4. once the AI Service Provider has received the MCP Data and incorporated it into the relevant Output, the AI Service Provider will immediately delete and destroy any MCP Data from its servers and systems (and certify that it has done so), and it further acknowledges and agrees to not use the MCP Data for any further purposes. 5. **THIRD PARTY APPLICATIONS** 1. The MCP integrates and communicates with the Configured AI Tool. You acknowledge and agree that any Configured AI Tool is not under GoCardless' control (and for the avoidance of doubt, is subject to the terms and conditions between you and the relevant AI Service Provider), and you further acknowledge and agree that GoCardless is not responsible or liable for any Configured AI Tool, including any Inputs or Outputs. 2. The inclusion or integration with any Configured AI Tool does not imply endorsement by GoCardless of that Configured AI Tool. 3. You further acknowledge and agree that GoCardless will not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with use or reliance on any Configured AI Tool, including the provision of any Outputs. Use of any Configured AI Tool and the Outputs created is solely at your own risk. 6. **INTELLECTUAL PROPERTY** 1. We are the owner or the licensee (as applicable) of all intellectual property rights subsisting in the CLI, MCP and/or MCP Data. Those works are protected by copyright laws and treaties around the world. All such rights are reserved. 2. You are not granted any right to use, and may not use, any of our intellectual property rights other than as set out in these Terms. 3. Subject to your compliance with these Terms, we grant you a non-transferable, non-sublicensable, non-exclusive, revocable, worldwide, royalty free and fully paid-up limited licence to copy and download the CLI and MCP onto the Customer Systems solely for the purposes of accessing the CLI and MCP to complete the Configuration Process. 4. Subject to your compliance with these Terms and following the successful completion of the Configuration Process, we grant you a non-transferable, non-sublicensable, non-exclusive, revocable, worldwide, royalty free and fully paid-up limited licence to use, and, subject to paragraph 4.2.4, for the AI Service Provider to use the MCP Data solely for the purposes of incorporating the relevant MCP Data into the relevant Output. 5. We may revoke or terminate the licences described in paragraphs 6.3 and 6.4 if you: (i) breach these Terms; or (ii) at our discretion without notice or liability. 6. Where any MCP Data is incorporated into the relevant Output ("**Incorporated MCP Data"**), all intellectual property rights subsisting in such Incorporated MCP Data will be retained by GoCardless, and the terms of paragraph 6.7 shall apply. 7. Subject to your compliance with these Terms, we grant you a non-transferable, non-sublicensable, non-exclusive, irrevocable, worldwide, royalty free and fully paid-up perpetual licence to use the Incorporated MCP Data in order to be able to use the relevant Output. 8. You grant to GoCardless a perpetual, worldwide, non-exclusive, royalty-free licence to use, copy, record, distribute, reproduce, disclose, sell, re-sell, sublicence, display, publicly perform, transmit, publish, broadcast, translate, make derivative works, and otherwise use and exploit in any manner whatsoever, all or any portion of any Inputs or Outputs (including any derivative works thereof) for any business purposes. 9. You acknowledge and agree that GoCardless and its licensors shall have a royalty-free, worldwide, transferable, sub-licensable, irrevocable, perpetual licence to use or incorporate into the CLI, MCP and/or MCP Data any enhancement requests or feedback provided by you, so long as you are not identified in any way as the source of such feedback. For the avoidance of doubt, GoCardless shall not be obliged to implement any such enhancement requires or feedback 7. **WARRANTIES** 1. You warrant and undertake that: 1. you are free to enter into these Terms and to perform the obligations imposed on you hereunder; 2. you shall comply with these Terms and all applicable law in relation to the exercise of your rights and fulfilment of your obligations under these Terms; 3. you own, or have a licence to use all rights (including intellectual property rights) in the Inputs and Outputs; 4. the use by us of any Inputs and Outputs in accordance with these Terms shall not infringe the rights, including the intellectual property rights, of any third-party; and 5. you shall not use the MCP Data made available via the MCP for any Prohibited AI Practices or in connection with any High-Risk Systems. 2. The CLI, MCP, MCP Data and/or any MCP Services (as applicable) received by you (including, for the avoidance of doubt, any Outputs) are provided on an "as is" basis. The express terms and conditions of these Terms will apply in place of all warranties, conditions, terms, representations, statements, undertakings and obligations implied by statute, common law, custom, trade usage or otherwise (including implied undertakings of satisfactory quality and fitness for purpose), all of which are excluded to the fullest extent permitted by law. 3. We do not warrant or guarantee that the CLI, MCP, MCP Data and/or any MCP Services received by you (including, for the avoidance of doubt, any Outputs) (as applicable) are correct, accurate, reliable, error-free, or free from any bias or hallucinations. 8. **LIABILITY** 1. Nothing in these Terms excludes or limits our or your liability for: 1. death or personal injury caused by our negligence; 2. wilful default or wilful misconduct; 3. fraud or fraudulent misrepresentation; 4. any other liability that cannot be excluded or limited by applicable law. 2. Your liability in respect of the indemnity in paragraph 8.6 is unlimited (and, accordingly, all limitations set out in this paragraph 8 will not apply to such liability). 3. We are not liable to you for any loss or damage, whether in contract, tort (including negligence), breach of statutory duty, or otherwise, even if foreseeable, arising under or in connection with: 1. your use of, or inability to use, the CLI, MCP, MCP Data and/or any Services (as applicable); or 2. your use of or reliance on any MCP Data or Outputs accessed through the MCP. 4. Subject to paragraph 8.1, and to the extent permitted under applicable law in no event shall we be liable to you for: 1. any loss of profits, loss of revenue, loss of corrupted data, damage to goodwill, loss of contracts, failure to realise anticipated savings (in each case, where arising directly or indirectly); or 2. any indirect or consequential loss or damage. 5. Subject to paragraph 8.1, our total aggregate liability, whether in contract, tort (including negligence and breach of statutory duty, howsoever arising), misrepresentation (whether negligent or innocent), restitution or otherwise, arising under or in connection with these Terms shall be limited to £50. 6. You agree to indemnify, defend, and hold harmless GoCardless and its affiliates, officers, directors, and employees (together the "**Indemnified Parties**"),in respect of any demand, loss, damage, cost, expense or liability (including all legal and other professional costs on a full indemnity basis) suffered or incurred by the Indemnified Parties as a result of: (i) any breach of these Terms; (ii) your misuse of the CLI, MCP, MCP Data and/or MCP Services (as applicable); (iii) any claim that the Inputs and Outputs infringes any rights of a third-party (including any intellectual property rights); (iv) any claims made by any third parties in respect of the CLI, MCP, MCP Data and/or MCP Services (as applicable); and( v) any claim made by any third party relating or arising out of processing of personal data. 7. GoCardless reserves the right, at your expense, to assume the exclusive defence and control of any matter for which you are required to indemnify the Indemnified Parties, and you agree to cooperate with GoCardless in defence of these claims. You agree not to settle any matter without the prior written consent of GoCardless. GoCardless will use reasonable efforts to notify you of any such claims upon becoming aware of it. 9. **TERMINATION** 1. GoCardless may terminate these Terms for convenience at any time In the event of termination by GoCardless pursuant to this paragraph 9.1, GoCardless shall have no further liability to you. 2. If you breach any of these Terms, we may immediately do any or all of the following (without limitation): 1. issue a warning to you; 2. issue legal proceedings against you for reimbursement of all costs resulting from the breach (including, but not limited to, reasonable administrative and legal costs); 3. take further legal action against you; and/or 4. disclose such information to law enforcement authorities as we reasonably feel is necessary to do so. 3. These Terms shall automatically terminate where GoCardless exercises its termination rights pursuant to these Terms. 4. We may terminate your access to or use of the CLI, MCP, MCP Data and/or Services (as applicable), or the AI Service Providers access to the MCP Data, immediately upon notice, if we determine, acting reasonably,without incurring liability to you: 1. that your use or access of the CLI, MCP, MCP Data and/or MCP Services: (a) poses a security risk to GoCardless, the CLI, MCP or MCP Data or any third party; (b) may adversely impact the availability or performance of the MCP, MCP Data or your ability to receive the MCP Services, or the systems or software of any other customer of GoCardless; (c) may subject us or any third party to any liability; or (d) may be fraudulent; or 2. that you are in breach of these Terms or any other agreement (including any agreement with the AI Service Provider in respect of your use of the Configured AI Tool). 5. On termination of these Terms for any reason: 1. subject to paragraph 6.7, you will not (and you will procure the AI Service Provider will not, as applicable) be permitted to use the MCP, MCP Data and/or MCP Services (as applicable), and you shall stop using the MCP, MCP Data and/or MCP Services (as applicable) immediately; 2. subject to paragraphs 6.7, 6.8 and 6.9, all licences granted under these Terms shall immediately terminate and you shall immediately cease all use of the MCP, MCP Data and/or MCP Services (as applicable). For the avoidance of doubt, any licences granted on a perpetual and irrevocable basis shall survive the termination of these Terms for any reason and shall continue in full force and effect; 3. you must immediately delete all copies of the CLI and MCP from the Customer Systems; 4. any rights, remedies, obligations or liabilities of the parties that have accrued up to the date of termination, including the right to claim damages in respect of any breach of these Terms which existed at or before the date of termination shall not be affected or prejudiced; and 5. the provisions of these Terms which by their nature should survive suspension or termination will survive. 10. **CHANGES TO THESE TERMS** 1. We may make changes to these Terms from time to time. Please check these Terms regularly to ensure that you understand the Terms that apply at the time that you access and use the MCP and MCP Data including to receive the MCP Services. **OTHER IMPORTANT INFORMATION** 2. Force Majeure. We shall not be in breach of these Terms nor liable for delay in performing, or failure to perform, any of our obligations under these Terms if such delay or failure results from events, circumstances or causes beyond our reasonable control, including, without limitation, strikes, lock-outs or other industrial disputes (whether involving our workforce or any other party), failure of a utility service or transport or telecommunications network or the internet, act of God, war, riot, civil commotion, malicious damage, compliance with any law or governmental order, rule, regulation or direction, accident, breakdown of plant or machinery, fire, flood, storm or default of suppliers or sub-contractors. In such circumstances we shall be entitled to a reasonable extension of the time for performing such obligations. 3. Entire Agreement. These Terms are the entire agreement between us related to the subject matter in these Terms. These Terms replace and supersede any other prior or contemporaneous agreement, representation or discussion, oral or written. 4. No Waiver. The failure to exercise, or delay in exercising, a right, power or remedy provided by these Terms or by law shall not constitute a waiver of that right, power or remedy. If a party waives a breach of any provision of these Terms, this shall not operate as a waiver of a subsequent breach of that provision, or as a waiver of a breach of any other provision. 5. Rights and Remedies. Except as expressly provided in these Terms, the rights and remedies provided under these Terms, are in addition to, and not exclusive of, any rights or remedies provided by law. 6. Severance. If any provision, or part of a provision, of these Terms is found by any court or authority of competent jurisdiction to be illegal, invalid or unenforceable, that provision or part-provision shall be deemed not to form part of these Terms, and the legality, validity or enforceability of the remainder of the provisions of these Terms shall not be affected, unless otherwise required by operation of applicable law. If any invalid, unenforceable or illegal provision would be valid, enforceable or legal if some part of it were modified, the provision shall apply with whatever modification is necessary to give effect to the commercial intention of the parties. 7. Assignment. You shall not, without the prior written consent of us assign, transfer, charge, sub-contract or deal in any other manner with all or any of its rights or obligations under these Terms. We may, at any time, assign, transfer, charge, sub-contract or deal in any other manner with all or any of its rights or obligations under these Terms. You shall enter into any further agreements reasonably required by us to give effect to any of the above. 8. Relationship of the Parties. Nothing in these Terms are intended to, or shall be deemed to, establish or constitute any partnership or joint venture between any of the parties, create a relationship of principal and agent for any purpose between the parties, or authorise either party to make or enter into any commitments for or on behalf of the other party. 9. Notices. Where we need to send you notices under these Terms or in connection with your use of the CLI, MCP, MCP Data and/or Services (as applicable), you acknowledge and agree to receive emails from us. All notices in relation to legal proceedings must be sent to [legalnotices@gocardless.com](mailto:legalnotices@gocardless.com). 10. For the purposes of these Terms, the following definitions will apply: 1. **"AI Service Provider"** means the service provider of the Configured AI Tool, and which you have entered into a separate agreement with so that you can access and use the Configured AI Tool; 2. **"EU AI Act"** means Regulation (EU) 2024/1689; 3. "**High Risk System**" means any AI system (or any part thereof) which is considered to be high-risk under the EU AI Act (cf. Art. 6 (1)-(3) EU AI Act); 4. **"Inputs"** means, following the successful completion of the Configuration Process in accordance with these Terms, any natural language prompt or other material, information or data inputted into the Configured AI Tool by you (or the AI Service Provider) and sent to the MCP in order to generate an Outputs; 5. "**Outputs"** means, following the successful completion of the Configuration Process in accordance with these Terms, any documentation, code, information, data, content, materials, and any other outputs generated by the Configured AI Tool in response to an Input and which includes MCP Data; 6. **"Prohibited AI Practices"** means the prohibited AI activities as defined in Article 5 of the EU AI Act or under any other applicable law. 11. **GOVERNING LAW AND JURISDICTION** 1. These terms and any dispute or claim arising out of or in connection with them or their subject matter or formation (including non-contractual disputes or claims) shall be governed by and construed in accordance with the law of England and Wales and you and we irrevocably agree that the courts of England and Wales shall have exclusive jurisdiction to settle any dispute or claim arising out of or in connection with these terms or their subject matter or formation (including non-contractual disputes or claims). Terms last updated 11 February 2026\. ## What's Next? #### [GC MCP](/docs/developer-resources/mcp) The GoCardless MCP enables you interact with GC's API via AI surfaces. ## Testing Webhooks (CLI) URL: https://docs.gocardless.com/docs/developer-resources/gc-cli/testing-webhooks-cli > Test and debug webhooks locally using the GoCardless CLI. # Testing Webhooks (CLI) [Webhooks](/docs/getting-started/stay-up-to-date-with-webhooks) let you receive real-time notifications from GoCardless when things happen in your merchant's account. You can use the `gocardless` CLI to test your webhook integration locally. Each event from GoCardless contains an [Event](/docs/api-reference/events/payment) object with a link to the modified resource. The CLI can trigger these events and either print them to the console or forward them to your local webhook handler. ## Listen for events ```bash gocardless listen ``` ``` Started listening for new webhooks. Any new webhooks will be printed to your console. ``` ## Trigger an event In a separate terminal tab, use the `trigger` command to fire a mock webhook: ```bash gocardless trigger mandate_activated ``` ``` This will trigger a mandate_activated event and create necessary resources in the process ⏳ Event triggered successfully, see dashboard for events 🚀 ``` You'll see the event payload in your `listen` tab: ```json { "action": "active", "created_at": "2022-02-24T12:49:32.066Z", "details": { "cause": "mandate_activated", "description": "The time window after submission has ended without errors, so this mandate is now active.", "origin": "gocardless" }, "id": "EV00QXTDGM5895", "links": { "mandate": "MD000K62KEVTEQ" }, "resource_type": "mandates" } ``` > **Info:** > The `trigger` command also creates any resources needed by the event. To target a specific > existing resource, use the resource flag (e.g. `--mandate MD000K62KEVTEQ`). Run `gocardless help > trigger` to see all available flags. ## Forward events to your webhook handler Use the `--forward` flag to pipe events to a running webhook server: ```bash gocardless listen --forward http://localhost:8001/webhook ``` Events will be forwarded to your webhook URL. Make sure your handler performs all the [recommended checks](/docs/getting-started/stay-up-to-date-with-webhooks#build-a-webhook-handler) when processing incoming webhooks. ## What's next? #### [Webhooks Guide](/docs/getting-started/stay-up-to-date-with-webhooks) Learn how to build a robust webhook handler. #### [CLI Reference](/docs/developer-resources/gc-cli/cli-reference) Full reference for all `gocardless` commands including `trigger` and `listen`. --- # Tutorials ## Handling Customer Notifications URL: https://docs.gocardless.com/docs/tutorials/handling-customer-notifications > Manage customer notifications for Direct Debit payments. # Handling Customer Notifications GoCardless automatically sends notifications to customers whenever an event happens in our system. For example, when a payment has been created, the customer will receive an email that informs them about the amount, description and cause of the payment. You have the ability to send some of these notifications yourself, and we'll honour your request if it is made within our stated deadline: otherwise, we will send the notification ourselves. **This feature is especially handy if you want to combine multiple notifications into a single one, for example:** - a welcome email which includes mandate setup information - an email that lists the schedule of all upcoming payments - an email that combines a notice of a new mandate and a new subscription **Here is an example of the workflow:** 1. Your integration creates a payment 2. The payment event schedules a `payment_created `notification 3. We send a webhook to your application which includes notification metadata 4. Your application notifies us that it will handle the notification **There are three conditions that you must satisfy to be able to handle a notification:** 1. You must be approved to handle notifications of this type 2. You must be the "notification owner" for that payment, mandate, or subscription 3. You must be on the Pro package > **Info: For Partners** > Note that your merchants do not need to be on the Pro package to use this feature. **Currently, the following notifications can be handled:** - `payment_created` - `mandate_created` - `subscription_created` ### Getting approved to handle notifications To be able to handle customer notifications yourself, you will need to be granted permission. Please get in touch with the [GoCardless support team](mailto:help@gocardless.com) to get started. > **Info:** > Our recommended workflow involves getting permissions in the sandbox environment, which will allow > you to test handling notifications. Once you've got compliant templates for those notifications, > you'll need to submit them for approval, after which GoCardless will then enable this feature in > the live environment. Permissions are very granular and cover the type & scheme of the notification. For example, you might be approved to handle the `payment_created` notification just in the scheme `sepa`. Compliant notifications must include all of the required information for that notification type, and be sent within the correct interval. More information about the required information for each type of notification can be found [in our platform guides](https://gocardless.com/direct-debit/notifications/). ### Notification ownership A merchant may be connected to multiple partners, or have multiple integrations, so to avoid the problem of multiple integrations all trying to handle the same notification, we track the "owner" for all customer notifications in our system. Only the owner will have the ability to handle notifications for that resource, falling back to GoCardless if the notification deadline is missed. The owner is usually defined as the creator of that resource. For example, if your integration creates a payment, the owner will be your integration. Currently, our system does not permit any kind of ownership transfer from one integration to another. Resources created via dashboard will not record any owner (and therefore cannot be handled by your integration). ### Getting notified about notifications Notification information is currently only delivered in webhooks. When your application receives a webhook, each event may include a `customer_notifications` payload, which contains a list of one or more notifications that were triggered by that event. (If you don't receive this information, it's because you are not the owner for that resource or have not been granted any permissions): ```http POST https://example.com/webhooks HTTP/1.1 Content-Type: application/json { "events": [ { "id": "EV123", "created_at": "2018-08-03T12:00:00.000Z", "action": "created", "resource_type": "payments", "links": { "payment": "PM123", }, "details": {}, "customer_notifications": [ { "id": "EV1D18JEXAMPLE", "type": "payment_created", "deadline": "2018-08-25T12:09:06.000Z", "mandatory": true } ] } ] } ``` Note that each notification for an event includes an `id`, `type`, `deadline` and `mandatory` flag: - `id `is used to handle the notification (see below) - `type `can be used to filter notifications that you don't handle. For example, if your integration only handles `payment_created `notifications, you can safely ignore notifications that are of another type. - `deadline `is the time by which your application must respond. If we don't hear from you before this deadline, we'll send the notification ourselves. The deadline is typically 10 minutes from the point at which we send the webhook but in the case of `payment_created `notifications, the deadline is the last possible time to notify the customer before the payment collects (this mirrors GoCardless' behaviour). - `mandatory `is whether the notification needs to be handled by somebody (currently always true). ### Handling notifications yourself If your application intends to handle a notification, you should let us know before you take action. If you wait until **after** sending the notification, there is a chance that we also sent it in the meantime (e.g. if the deadline had elapsed), which would result in the customer receiving two notifications, one from each of us. > **Info:** > If you had already sent the notification(s) previously (e.g. a welcome email which included > mandate setup information, or an email that listed upcoming payments including this one), you'll > still need to tell us that you have handled each notification. So, we recommend that you declare your intent first, and then send the notification using whichever mechanism is most appropriate for your system: ```http POST https://api.gocardless.com/customer_notifications/EV1D18JEXAMPLE/actions/handle HTTP/1.1 HTTP/1.1 201 Created { "customer_notifications": { "id": "EV1D18JEXAMPLE", "type": "payment_created", "action_taken": "handled", "action_taken_at": "2018-08-01T13:42:56.000Z", "action_taken_by": "Partner name", "links": { "customer": "CU123", "event": "EV123", "payment": "PM123" } } } ``` ```php $access_token, 'environment' => \GoCardlessPro\Environment::SANDBOX ]); // Each webhook may contain multiple events to handle, batched together foreach ($events as $event) { // We might want to handle mandate_created emails and send an email which // includes both the mandate and upcoming payments for it. foreach ($events->customer_notifications as $notification) { if ($notification->type === "mandate_created") { $client->customerNotifications()->handle($notification->id); // We recommend processing data asynchronously, so as to // promptly respond to the webhook and avoid timeouts. In this // example, the application uses a message queue to send the // email later. \MyNotificationsSystem::enqueue($notification, $event); } elseif ($notification->type === "payment_created") { // If your mandate_created email properly notifies of the // payment schedule, we still need to handle the payment_created // notification to prevent GoCardless from sending it. $client->customerNotifications()->handle($notification->id); } } } header("HTTP/1.1 204 No Content"); } catch(\GoCardlessPro\Core\Exception\InvalidSignatureException $e) { header("HTTP/1.1 498 Invalid Token"); } ``` ```python # Here, we're using a Django view, but essentially the same code will work in # other Python web frameworks (e.g. Flask) with minimal changes import os from django.views.generic import View from django.views.decorators.csrf import csrf_exempt from django.utils.decorators import method_decorator from django.http import HttpResponse from gocardless_pro import webhooks, Client from gocardless_pro.errors import InvalidSignatureError from my_services import my_notification_system # Handle the incoming Webhook and check its signature. class Webhook(View): @method_decorator(csrf_exempt) def dispatch(self, *args, **kwargs): return super(Webhook, self).dispatch(*args, **kwargs) def get_events(self, request): # We recommend storing your webhook endpoint secret in an environment # variable for security secret = os.environ['GC_WEBHOOK_SECRET'] signature = request.META["HTTP_WEBHOOK_SIGNATURE"] body = request.body.strip() # The parse method will first verify the signature of the webhook body # in order to ensure it has not been tampered with. Without a valid # signature, a gocardless_pro.errors.InvalidSignatureError will be # thrown. return webhooks.parse(body, secret, signature) def post(self, request, *args, **kwargs): client = Client(access_token=os.environ['GC_TOKEN'], environment='live') try: # We might want to handle mandate_created emails and send an email # which includes both the mandate and upcoming payments for it. for event in self.get_events(request): for notification in event.customer_notifications: if notification.type == "mandate_created": client.customer_notifications.handle(notification.id) # We recommend processing data asynchronously, so as to # promptly respond to the webhook and avoid timeouts. In # this example, the application uses a message queue to # send the email. my_notification_system.enqueue_email(notification, event) elif notification.type == "payment_created": # If your mandate_created email properly notifies of the # payment schedule, we still need to handle the # payment_created notification to prevent GoCardless # from sending it. client.customer_notifications.handle(notification.id) return HttpResponse(200) except InvalidSignatureError: return HttpResponse(498) ``` ```ruby require "gocardless_pro" client = GoCardlessPro::Client.new( access_token: ENV["GC_ACCESS_TOKEN"], environment: :sandbox, ) args = { request_body: request.body, signature_header: request.headers["Webhook-Signature"], # We recommend storing your webhook endpoint secret in an environment variable # for security webhook_endpoint_secret: ENV["WEBHOOK_SECRET"] } # The parse method will first verify the signature of the webhook body # in order to ensure it has not been tampered with. Without a valid # signature, a GocardlessPro::Webhook::InvalidSignatureError will be # thrown. begin GoCardlessPro::Webhook.parse(**args).each do |event| notifications = event.customer_notifications # We might want to handle mandate_created emails and send an email which # includes both the mandate and upcoming payments for it. mandate_notifications = notifications.select { |n| n.type == "mandate_created" } mandate_notifications.each do |notification| client.customer_notifications.handle(notification.id) # We recommend processing data asynchronously, so as to promptly respond to # the webhook and avoid timeouts. In this example, the application uses a # message queue to send the email. MyNotificationSystem.enqueue_email(notification, event) end # If your mandate_created email properly notifies of the payment schedule, we # still need to handle the payment_created notification to prevent GoCardless # from sending it. payment_notifications = notifications.select { |n| n.type == "payment_created" } payment_notifications.each do |notification| client.customer_notifications.handle(notification.id) end end head 204 rescue GocardlessPro::Webhook::InvalidSignatureError head 498 end ``` ```java package com.myInvoicingApp; // Use the POM file at // https://raw.githubusercontent.com/gocardless/gocardless-pro-java-maven-example/master/pom.xml import com.gocardless.errors.InvalidSignatureException; import com.gocardless.resources.Event; import com.gocardless.resources.CustomerNotification; import com.gocardless.resources.CustomerNotification.Type; import com.myInvoicingApp.queue.MessageQueue; import com.myInvoicingApp.queue.PendingNotificationMessage; import java.util.List; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; import org.springframework.beans.factory.annotation.Autowired; @RestController public class WebhookHandler { @Autowired MessageQueue messageQueue; @PostMapping("/") public ResponseEntity handlePost( @RequestHeader("Webhook-Signature") String signatureHeader, @RequestBody String requestBody) { try { // We recommend storing your webhook endpoint secret in an environment variable // for security String webhookEndpointSecret = System.getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET"); // The parse method will first verify the signature of the webhook body // in order to ensure it has not been tampered with. Without a valid // signature, a com.gocardless.errors.InvalidSignatureException will be // thrown. List events = Webhook.parse( requestBody, signatureHeader, webhookEndpointSecret ); // We might want to handle mandate_created emails and send an email which // includes both the mandate and upcoming payments for it. for (Event event : events) { for (CustomerNotification n : event.getCustomerNotifications()) { if (n.getType() == Type.MANDATE_CREATED) { sendNotification(n, event); client.customerNotifications().handle(n.getId()); } else if (n.getType() == Type.PAYMENT_CREATED) { // If your mandate_created email properly notifies of // the payment schedule, we still need to handle the // payment_created notification to prevent GoCardless // from sending it. client.customerNotifications().handle(n.getId()); } } } return new ResponseEntity("", HttpStatus.NoContent); } catch(InvalidSignatureException e) { return new ResponseEntity( "Incorrect Signature", HttpStatus.BAD_REQUEST ); } } private void sendNotification(CustomerNotification notification, Event event) { // We recommend processing data asynchronously, so as to promptly // respond to the webhook and avoid timeouts. In this example, the // application uses a message queue to send the email later. messageQueue.enqueue(new PendingNotificationMessage(notification, event)); } } ``` ```javascript const process = require("process"); const http = require("http"); const webhooks = require("gocardless-nodejs/webhooks"); const webhookEndpointSecret = process.env.WEBHOOK_ENDPOINT_SECRET; const server = http.createServer(function (request, response) { if (request.method !== "POST") { response.writeHead(405); response.end(); return; } let data = ""; request.on("data", (chunk) => { data += chunk; }); request.on("end", () => { try { const signatureHeader = request.headers["webhook-signature"]; const events = webhooks.parse(data, webhookEndpointSecret, signatureHeader); response.writeHead(204); response.end(); } catch (e) { response.writeHead(403); response.end(); } }); }); const port = 3000; const host = "127.0.0.1"; server.listen(port, host); console.log(`Listening at http://${host}:${port}`); ``` ```net [HttpPost] public ActionResult HandleWebhook() { var requestBody = Request.InputStream; requestBody.Seek(0, System.IO.SeekOrigin.Begin); var requestJson = new StreamReader(requestBody).ReadToEnd(); // We recommend storing your webhook endpoint secret in an environment variable // for security var secret = ConfigurationManager.AppSettings["GoCardlessWebhookSecret"]; var signature = Request.Headers["Webhook-Signature"]; // We might want to handle mandate_created emails and send an email which // includes both the mandate and upcoming payments for it. try { // The Parse method will first verify the signature of the webhook body // in order to ensure it has not been tampered with. Without a valid // signature, a InvalidSignatureException will be thrown. foreach (Event event in WebhookParser.Parse(requestJson, secret, signature)) { foreach (GoCardless.Resources.CustomerNotifications notification in eventResource.CustomerNotifications) { if (notification.Type == "mandate_created") { // We recommend processing data asynchronously, so as to // promptly respond to the webhook and avoid timeouts. In this // example, the application uses a message queue to send the // email later. MyNotificationSystem.Enqueue(notification, event); await client.CustomerNotifications.HandleAsync(notification.Id); } if (notification.Type == "payment_created") { // If your mandate_created email properly notifies of the // payment schedule, we still need to handle the payment_created // notification to prevent GoCardless from sending it. await client.CustomerNotifications.HandleAsync(notification.Id); } } } return new HttpStatusCodeResult(HttpStatusCode.OK); } catch (InvalidSignatureException e) { return new HttpStatusCodeResult(HttpStatusCode.Forbidden); } } ``` ```go package main import ( "context" "fmt" "http" gocardless "github.com/gocardless/gocardless-pro-go/v6" ) type PendingNotification struct { event gocardless.Event customerNotification gocardless.CustomerNotification } func main() { accessToken := "your_access_token_here" config, err := gocardless.NewConfig(accessToken, gocardless.WithEndpoint(gocardless.SandboxEndpoint)) if err != nil { fmt.Printf("got err in initialising config: %s", err.Error()) return } client, err := gocardless.New(config) if err != nil { fmt.Println("error in initialisating client: %s", err.Error()) return } sendNotification := func(n gocardless.CustomerNotification, event gocardless.Event) { pendingNotification := PendingNotification{ event: event, customerNotification: n, } messageQueue.Enqueue(pendingNotification) } parseEvent := func(event gocardless.Event) { for _, n := range event.CustomerNotifications() { if n.Type == "mandate_created" { sendNotification(n, event) ctx := context.TODO() customerNotificationHandleParams := gocardless.CustomerNotificationHandleParams{} client.CustomerNotifications.Handle(ctx, n.Id, customerNotificationHandleParams) } } } http.HandleFunc("/webhookEndpoint", func(w http.ResponseWriter, r *http.Request) { wh, err := gocardless.NewWebhookHandler("secret", gocardless.EventHandlerFunc(func(event gocardless.Event) error { parseEvent(event) })) wh.ServeHTTP(w, r) }) } ``` Alternatively, if your application does not respond, or does not respond before the deadline, GoCardless will send the notification instead and there will be no opportunity to handle after that point. In all cases, GoCardless will record the outcome for each notification for audit purposes. > **Info:** > If you are taking payments in Denmark, please note that Danish banks typically provide a monthly > summary of requested payments to their customers. For this reason, **GoCardless does not send > `payment_created` notifications to Danish payers**, to avoid double-notifying them. If you wish to > send a payment-related notification, you can of course do so, but bear in mind that it will not be > the only one received by the payer. ## What's next? ## Handling Tax URL: https://docs.gocardless.com/docs/tutorials/handling-tax > Handle tax calculations for GoCardless payments. # Handling Tax GoCardless has been instructed by the relevant authorities to start charging tax on its fees. These guidelines aim to help accounting partners implement the required changes to ensure their merchant's accounts can still reconcile, and accurately report tax. > **Info:** > This guide may be relevant to you if you are an accounting software partner or interfacing with an > accounting software and you need to account for VAT correctly. ## Which merchant does this impact? At this time, this change will impact any merchants who have a `country_code` of "GB" or "FR". It is possible that we may have to start charging VAT (or equivalent) in other areas where we operate in the future. ## UX/UI best practice Based on the rounds of user testing we conducted with participants, we recommend the following patterns for UX/UI best practice. ### Payment detail view When showing tax in the payment in detail view, we recommend surfacing the total amount of tax from fees within the source currency at the time the payment was taken. ![01-payment-detail-view-example](/images/docs/tutorials/handling-tax/01-payment-detail-view-example.png) ### Payout detail view The same recommendation should be applied on the payout level. Show the total amount of tax on fees within the source currency. ![02-payout-detail-view-example](/images/docs/tutorials/handling-tax/02-payout-detail-view-example.png) _We recommend following the same best practice when showing VATs within emails._ There are now three different properties of a payout that we need to think about: **Payer Currency** - this is the currency the money was originally collected in **FX Currency** - this is the currency that the money will be received in a merchant bank account in **Tax Currency** - this is the currency in which the merchant pays tax To help our discussion, we are going to imagine a set of different payouts. If your product does not support all of these, you may ignore the guidance related to those categories. We are using the tax_jurisdiction 'GB' for these examples. Any merchants with a tax jurisdiction 'FR' will apply the same logic (but with Euros) | Category | Payer Currency | FX Currency | Tax Currency | | -------------- | -------------- | ----------- | ------------ | | **Category A** | GBP | - | GBP | | **Category B** | USD | GBP | GBP | | **Category C** | USD | - | GBP | | **Category D** | NZD | AUD | GBP | | **Category E** | USD | USD | - | ## A Note on Tax Exchange Rates Tax is still due on money moved in currencies other than GBP. For example, our _Category C_ merchant is a GB merchant taking USD payments into a USD bank account. However, GoCardless still needs to pay tax to the UK government in GBP. To accomplish this, we have to apply an exchange rate to the tax, for reporting purposes. When the exchange rate has been finalised you will receive the `tax_exchange_rates_confirmed` webhook. This could be a long time (e.g. a few weeks) after the payout is created. At this point, you can pull [payout_items](/docs/api-reference/payout-item#get-all-payout-items-in-a-single-payout) and the `tax_exchange_rate` will be present on each `taxes` object. We recommend that you store this exchange rate in your own systems, as it will be required so that the merchant can correctly claim back tax from the relevant government. ## Handling tax before September 1st 2020? From the 1st September, any [payout_items](/docs/api-reference/payout-item#get-all-payout-items-in-a-single-payout) will include tax information in the API. If you want to see tax information on payout items between April 2020 and September 2020, you must opt in by providing the `include_2020_tax_cutover` parameter when querying the `payout_items` API endpoint. ## How to process payout fees When processing your payout, this change should only impact the way you process fees. Everything else (the net payout and any FX realised gains) should remain the same. > **Info:** > The total amount of fees deducted from a payout will still be in the payout object under > `deducted_fees`. However, previously it was possible to handle all the separate fee line items as > one entity, ignoring payout_items and just using the `deducted_fees` value. Unfortunately, it is > possible (although unlikely) that different fees within the same payout could have a different tax > rate - e.g. if the tax rate changes. ### Option 1: Create one transaction per fee line item This may be what you are already doing, in which case it's the obvious choice. This is useful if you want to display fees connected to specific payments, and also future-proofs your integration against more complicated tax setups (e.g. with multiple taxes applied to one fee. 1. [`Get the payout_items`](/docs/api-reference/payout-item#get-all-payout-items-in-a-single-payout) 2. For each payout item that has a `taxes `array, iterate through each item and apply the corresponding tax in your system using the `tax_rate_id `and `exchange_rate `provided ### Option 2: Group wherever possible If you currently only create one fee transaction per payout, this may be a useful approach to avoid confusing merchants. The vast majority of payouts will have a single tax type applied, and the same exchange rate across all items (or no exchange rate), so you can group them and (most of the time) you will end up with a single fee transaction per payout. However, it's more complicated to implement. It also relies on the current behaviour that there will only be one tax applied to each transaction (which is true in GB and FR, but might not be forever). 1. [`Get the payout_items`](/docs/api-reference/payout-item#get-all-payout-items-in-a-single-payout) 2. Group the fees by `taxes[tax_rate_id]` 3. If the taxes have to be converted (e.g. _Category C & Category D_ ), then also grouped by the exchange rate `taxes[exchange_rate]`. 4. Create one transaction for each of these 'groups', summing the fees, and using the `tax_rate_id `and `exchange_rate `provided | | **Tax Applied?** | **Tax Exchange Rate required?** | **Payout Webhook(s) required to process** | | -------------- | ---------------- | ------------------------------- | ------------------------------------------------------ | | **Category A** | Yes | No | `paid` | | **Category B** | No | No | `fx_rate_confirmed` | | **Category C** | Yes | Yes | `tax_exchange_rates_confirmed` | | **Category D** | Yes | Yes | `fx_rate_confirmed `and `tax_exchange_rates_confirmed` | | **Category E** | No | No | `paid` | You can tell if tax is applied by seeing whether the payout `tax_currency` is populated. You can tell if the tax exchange rate is required by seeing if `tax_currency` is the same as the payout `fx[currency]` or `currency` if not FX. As shown in the above table, for any payouts with a tax exchange rate required (i.e. _Category C_ or _Category D_), you will need to wait for the new `tax_exchange_rates_confirmed` webhook. ### Using Tax Rates Each tax rate has an ID (e.g. `FR_VAT_1`). The number at the end will be incremented if the tax rate changes, a full list of tax rates can be [found here](/docs/api-reference/tax-rates) If you need more information about our tax rates programmatically (e.g. if you want to be able to auto-create tax rates in your own system) there is a new [Tax Rates API](/docs/api-reference/tax-rates) that will provide the percentage and jurisdiction. ### Special Cases #### Committed Revenue Merchants Merchants with committed revenue contracts do not have any fees deducted from their payouts and are instead invoiced at the end of the month. At this time, we expect these invoices (and therefore the tax implications) to be handled outside of a partner integration. Therefore we believe no change will be required. These merchants can be identified because the `deducted_fees` property on the `payout` will be 0. #### Overseas Territories Territories such as Guadeloupe have their own tax regimes, and as such can have different tax rates. They will have their own tax rates, with different IDs, and will need to be processed accordingly. A full list of tax rates can be [found here](/docs/api-reference/tax-rates) ### Fee Reversals If a payment undergoes a late failure, the GoCardless fee is also reversed. The `taxes` array will be the same as when it was originally charged. Depending on your setup, you may want to reverse the original transaction or create an inverse transaction to 'cancel' the previous one. Late failures can happen a long time after the original payment was taken, so it's worth considering that the accounts for the previous year may have already closed. ## What's next? --- # API Reference — Resources ## balance URL: https://docs.gocardless.com/docs/api-reference/balance # Balance Source: https://docs.gocardless.com/docs/api-reference/balance ## List balances `GET /balances` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of balances for a given creditor. This endpoint is rate limited to 60 requests per minute. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `creditor` | query | string | Yes | ID of a [creditor](#core-endpoints-creditors). | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `balances` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `balance_type` | enum | No | Type of the balance. Could be one of - `pending_payments_submitted`: Payments we have submitted to the scheme but not yet confirmed. This does not exactly correspond to Pending payments in the dashboard, because this balance does not include payments that are pending submission. - `confirmed_funds`: Payments that have been confirmed minus fees and unclaimed debits for refunds, failures and chargebacks. These funds have not yet been moved into a payout. - `pending_payouts`: Confirmed payments that have been moved into a payout. This is the total due to be paid into your bank account in the next payout run (payouts happen once every business day). `pending_payouts` will only be non-zero while we are generating and submitting the payouts to our partner bank. | | `amount` | integer | No | The total amount in the balance, defined as the sum of all debits subtracted from the sum of all credits, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `last_updated_at` | string | No | Dynamic [timestamp](#api-usage-dates-and-times) recording when this resource was last updated. | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## bank-account-detail URL: https://docs.gocardless.com/docs/api-reference/bank-account-detail # Bank Account Detail Source: https://docs.gocardless.com/docs/api-reference/bank-account-detail ## Get encrypted bank details `GET /bank_account_details/{customer_bank_account_id}` Returns bank account details in the flattened JSON Web Encryption format described in RFC 7516. You must specify a `Gc-Key-Id` header when using this endpoint. See [Public Key Setup](https://developer.gocardless.com/gc-embed/bank-details-access#public_key_setup) for more details.

Restricted: This endpoint is restricted to organisations with the Encrypted Bank Details Access upgrade

Note: See our [Security Requirements](#appendix-security-requirements) before using this feature

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_bank_account_id` | path | string | Yes | The customer bank account id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `bank_account_details` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `protected` | string | No | Base64 URL encoded JWE header values, containing the following keys: - `alg`: the asymmetric encryption type used to encrypt symmetric key, e.g: `RSA-OAEP`. - `enc`: the content encryption type, e.g: `A256GCM`. - `kid`: the ID of an RSA-2048 public key, from your JWKS, used to encrypt the AES key. | | `encrypted_key` | string | No | Base64 URL encoded symmetric content encryption key, encrypted with the asymmetric key from your JWKS. | | `iv` | string | No | Base64 URL encoded initialization vector, used during content encryption. | | `ciphertext` | string | No | Base64 URL encoded encrypted payload, in this case bank details. | | `tag` | string | No | Base64 URL encoded authentication tag, used to verify payload integrity during decryption. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## bank-account-holder-verification URL: https://docs.gocardless.com/docs/api-reference/bank-account-holder-verification # Bank Account Holder Verification Source: https://docs.gocardless.com/docs/api-reference/bank-account-holder-verification ## Create a bank account holder verification. `POST /bank_account_holder_verifications` Verify the account holder of the bank account. A complete verification can be attached when creating an outbound payment. This endpoint allows partner merchants to create Confirmation of Payee checks on customer bank accounts before sending outbound payments.

Restricted: This endpoint is restricted to organisations with Outbound Payments enabled

### Request body Wrap request body attributes in a `bank_account_holder_verifications` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `type` | enum | Yes | Type of the verification that has been performed eg. [Confirmation of Payee](https://www.wearepay.uk/what-we-do/overlay-services/confirmation-of-payee/) | | `reference` | string \| null | No | An alphanumeric reference code used by some financial institutions to identify an individual account. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `bank_account_holder_verifications` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | The unique identifier for the bank account holder verification resource, e.g. "BAHV123". | | `type` | enum | Yes | Type of the verification that has been performed eg. [Confirmation of Payee](https://www.wearepay.uk/what-we-do/overlay-services/confirmation-of-payee/) | | `result` | enum | No | Result of the verification, could be one of - `full_match`: The verification has confirmed that the account name exactly matches the details provided. - `partial_match`: The verification has confirmed that the account name is similar but does not match to the details provided. - `no_match`: The verification concludes the provided name does not match the account details. - `unable_to_match`: The verification could not be performed due to recipient bank issues or technical issues | | `actual_account_name` | string \| null | No | The actual account name returned by the recipient's bank, populated only in the case of a partial match. | | `status` | enum | Yes | The status of the bank account holder verification. - `pending`: We have triggered the verification, but the result has not come back yet. - `completed`: The verification is complete and is ready to be used. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a bank account holder verification. `GET /bank_account_holder_verifications/{bank_account_holder_verification_id}` Fetches a bank account holder verification by ID. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `bank_account_holder_verification_id` | path | string | Yes | The bank account holder verification id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `bank_account_holder_verifications` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | The unique identifier for the bank account holder verification resource, e.g. "BAHV123". | | `type` | enum | Yes | Type of the verification that has been performed eg. [Confirmation of Payee](https://www.wearepay.uk/what-we-do/overlay-services/confirmation-of-payee/) | | `result` | enum | No | Result of the verification, could be one of - `full_match`: The verification has confirmed that the account name exactly matches the details provided. - `partial_match`: The verification has confirmed that the account name is similar but does not match to the details provided. - `no_match`: The verification concludes the provided name does not match the account details. - `unable_to_match`: The verification could not be performed due to recipient bank issues or technical issues | | `actual_account_name` | string \| null | No | The actual account name returned by the recipient's bank, populated only in the case of a partial match. | | `status` | enum | Yes | The status of the bank account holder verification. - `pending`: We have triggered the verification, but the result has not come back yet. - `completed`: The verification is complete and is ready to be used. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## bank-authorisation URL: https://docs.gocardless.com/docs/api-reference/bank-authorisation # Bank Authorisation Source: https://docs.gocardless.com/docs/api-reference/bank-authorisation ## Create a Bank Authorisation `POST /bank_authorisations` Create a Bank Authorisation.

Restricted: this endpoint is restricted as the authorisation must be used within a checkout flow that meets regulatory requirements for each payment scheme. Integrators should use a Billing Request Flow to do this.

If you would like to enable bank authorisations, you will need to go through a separate compliance process. For more details please get in touch.

### Request body Wrap request body attributes in a `bank_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `redirect_uri` | string | No | URL that the payer can be redirected to after authorising the payment. On completion of bank authorisation, the query parameter of either `outcome=success` or `outcome=failure` will be appended to the `redirect_uri` to indicate the result of the bank authorisation. If the bank authorisation is expired, the query parameter `outcome=timeout` will be appended to the `redirect_uri`, in which case you should prompt the user to try the bank authorisation step again. Please note: bank authorisations can still fail despite an `outcome=success` on the `redirect_uri`. It is therefore recommended to wait for the relevant bank authorisation event, such as [`BANK_AUTHORISATION_AUTHORISED`](#billing-request-bankauthorisationauthorised), [`BANK_AUTHORISATION_DENIED`](#billing-request-bankauthorisationdenied), or [`BANK_AUTHORISATION_FAILED`](#billing-request-bankauthorisationfailed) in order to show the correct outcome to the user. The BillingRequestFlow ID will also be appended to the `redirect_uri` as query parameter `id=BRF123`. Defaults to `https://pay.gocardless.com/billing/static/thankyou`. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `bank_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BAU". | | `redirect_uri` | string | No | URL that the payer can be redirected to after authorising the payment. On completion of bank authorisation, the query parameter of either `outcome=success` or `outcome=failure` will be appended to the `redirect_uri` to indicate the result of the bank authorisation. If the bank authorisation is expired, the query parameter `outcome=timeout` will be appended to the `redirect_uri`, in which case you should prompt the user to try the bank authorisation step again. Please note: bank authorisations can still fail despite an `outcome=success` on the `redirect_uri`. It is therefore recommended to wait for the relevant bank authorisation event, such as [`BANK_AUTHORISATION_AUTHORISED`](#billing-request-bankauthorisationauthorised), [`BANK_AUTHORISATION_DENIED`](#billing-request-bankauthorisationdenied), or [`BANK_AUTHORISATION_FAILED`](#billing-request-bankauthorisationfailed) in order to show the correct outcome to the user. The BillingRequestFlow ID will also be appended to the `redirect_uri` as query parameter `id=BRF123`. Defaults to `https://pay.gocardless.com/billing/static/thankyou`. | | `url` | string \| null | No | URL for an oauth flow that will allow the user to authorise the payment | | `qr_code_url` | string \| null | No | URL to a QR code PNG image of the bank authorisation url. This QR code can be used as an alternative to providing the `url` to the payer to allow them to authorise with their mobile devices. | | `authorisation_type` | enum | No | Type of authorisation, can be either 'mandate' or 'payment'. | | `created_at` | string | No | Timestamp when the flow was created | | `expires_at` | string | No | Timestamp when the url will expire. Each authorisation url currently lasts for 15 minutes, but this can vary by bank. | | `last_visited_at` | string \| null | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the authorisation URL has been visited. | | `authorised_at` | string \| null | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the user has been authorised. | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a Bank Authorisation `GET /bank_authorisations/{bank_authorisation_id}` Get a single bank authorisation. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `bank_authorisation_id` | path | string | Yes | The bank authorisation id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `bank_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BAU". | | `redirect_uri` | string | No | URL that the payer can be redirected to after authorising the payment. On completion of bank authorisation, the query parameter of either `outcome=success` or `outcome=failure` will be appended to the `redirect_uri` to indicate the result of the bank authorisation. If the bank authorisation is expired, the query parameter `outcome=timeout` will be appended to the `redirect_uri`, in which case you should prompt the user to try the bank authorisation step again. Please note: bank authorisations can still fail despite an `outcome=success` on the `redirect_uri`. It is therefore recommended to wait for the relevant bank authorisation event, such as [`BANK_AUTHORISATION_AUTHORISED`](#billing-request-bankauthorisationauthorised), [`BANK_AUTHORISATION_DENIED`](#billing-request-bankauthorisationdenied), or [`BANK_AUTHORISATION_FAILED`](#billing-request-bankauthorisationfailed) in order to show the correct outcome to the user. The BillingRequestFlow ID will also be appended to the `redirect_uri` as query parameter `id=BRF123`. Defaults to `https://pay.gocardless.com/billing/static/thankyou`. | | `url` | string \| null | No | URL for an oauth flow that will allow the user to authorise the payment | | `qr_code_url` | string \| null | No | URL to a QR code PNG image of the bank authorisation url. This QR code can be used as an alternative to providing the `url` to the payer to allow them to authorise with their mobile devices. | | `authorisation_type` | enum | No | Type of authorisation, can be either 'mandate' or 'payment'. | | `created_at` | string | No | Timestamp when the flow was created | | `expires_at` | string | No | Timestamp when the url will expire. Each authorisation url currently lasts for 15 minutes, but this can vary by bank. | | `last_visited_at` | string \| null | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the authorisation URL has been visited. | | `authorised_at` | string \| null | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the user has been authorised. | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## bank-details-lookup URL: https://docs.gocardless.com/docs/api-reference/bank-details-lookup # Bank Details Lookup Source: https://docs.gocardless.com/docs/api-reference/bank-details-lookup ## Perform a bank details lookup `POST /bank_details_lookups` Performs a bank details lookup. As part of the lookup, a modulus check and reachability check are performed. For UK or Eurozone-based bank accounts, where an account holder name is provided (and an account number, a sort code or an IBAN are already present), we verify that the account holder name and bank account number match the details held by the relevant bank. If there is no match, the endpoint will return a 422 - validation error on account_holder_name: "Account holder name does not match bank account details provided". If your request returns an [error](#api-usage-errors) or the `available_debit_schemes` attribute is an empty array, you will not be able to collect payments from the specified bank account. GoCardless may be able to collect payments from an account even if no `bic` is returned. Bank account details may be supplied using [local details](#appendix-local-bank-details) or an IBAN. _ACH scheme_ For compliance reasons, an extra validation step is done using a third-party provider to make sure the customer's bank account can accept Direct Debit. If a bank account is discovered to be closed or invalid, the customer is requested to adjust the account number/routing number and succeed in this check to continue with the flow. _Note:_ Usage of this endpoint is monitored. If your organisation relies on GoCardless for modulus or reachability checking but not for payment collection, please get in touch. ### Request body Wrap request body attributes in a `bank_details_lookups` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `iban` | string \| null | No | International Bank Account Number. Alternatively you can provide [local details](#appendix-local-bank-details). | | `account_number` | string \| null | No | Bank account number - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `bank_code` | string \| null | No | Bank code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `branch_code` | string \| null | No | Branch code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `country_code` | string \| null | No | [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code. Must be provided if specifying local details. | | `account_holder_name` | string \| null | No | The account holder name associated with the account number (if available). If provided and the country code is GB, a payer name verification will be performed. | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `bank_details_lookups` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `bank_name` | string \| null | Yes | The name of the bank with which the account is held (if available). | | `bic` | string \| null | Yes | ISO 9362 SWIFT BIC of the bank with which the account is held.

Even if no BIC is returned for an account, GoCardless may still be able to collect payments from it - you should refer to the available_debit_schemes attribute to determine reachability.

| | `available_debit_schemes` | array | Yes | Array of [schemes](#mandates_scheme) supported for this bank account. This will be an empty array if the bank account is not reachable by any schemes. | | `payer_name_verification_result` | enum \| null | Yes | The result of the payer name verification check performed during the lookup. `null` if no check was performed. - `full`: The name provided matches the name held by the bank. - `close`: The name provided is a close but not exact match to the name held by the bank. - `cannot_perform_verification`: A verification was attempted but could not be completed. This can happen for a number of reasons, including the account holder's bank not participating in the verification scheme, the account not being eligible for verification (e.g. the account holder has opted out), or the bank details not being resolvable, among others. - `null`: Verification was not triggered. Either PNV is not supported for the scheme, or PNV feature is disabled for your organisation. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## billing-request URL: https://docs.gocardless.com/docs/api-reference/billing-request # Billing Request Source: https://docs.gocardless.com/docs/api-reference/billing-request ## Create a Billing Request `POST /billing_requests`

Important: All properties associated with subscription_request and instalment_schedule_request are only supported for ACH and PAD schemes.

Note: Pay by Bank is only available for transactions in GBP with your customers in the UK and for EUR with your customers in supported Eurozone countries. We will be adding other countries soon.

Warning: by default, the ability to provide a custom mandate reference is switched off. The banking system rules for valid references are quite complex, and we recommend allowing GoCardless to generate it. If you would like to provide custom references, please contact support.

### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `mandate_request` | object | No | | | `payment_request` | object | No | | | `subscription_request` | object | No | | | `instalment_schedule_request` | object | No | | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List Billing Requests `GET /billing_requests` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your billing requests. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `status` | query | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `customer` | query | string | No | ID of a [customer](#core-endpoints-customers). If specified, this endpoint will return all requests for the given customer. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `billing_requests` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BRQ". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Collect customer details `POST /billing_requests/{billing_request_id}/actions/collect_customer_details` If the billing request has a pending collect_customer_details action, this endpoint can be used to collect the details in order to complete it. The endpoint takes the same payload as Customers, but checks that the customer fields are populated correctly for the billing request scheme. Whatever is provided to this endpoint is used to update the referenced customer, and will take effect immediately after the request is successful. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `customer` | object | No | | | `customer_billing_detail` | object | No | | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Collect bank account details `POST /billing_requests/{billing_request_id}/actions/collect_bank_account` If the billing request has a pending collect_bank_account action, this endpoint can be used to collect the details in order to complete it. The endpoint takes the same payload as Customer Bank Accounts, but check the bank account is valid for the billing request scheme before creating and attaching it. If the scheme is PayTo and the pay_id is available, this can be included in the payload along with the country_code. _ACH scheme_ For compliance reasons, an extra validation step is done using a third-party provider to make sure the customer's bank account can accept Direct Debit. If a bank account is discovered to be closed or invalid, the customer is requested to adjust the account number/routing number and succeed in this check to continue with the flow. _BACS and SEPA schemes_ [Payer Name Verification](https://hub.gocardless.com/s/article/Introduction-to-Payer-Name-Verification?language=en_GB) is enabled by default for UK and Eurozone based bank accounts, meaning we verify the account holder name and bank account number/IBAN match the details held by the relevant bank. If there is no match, the endpoint will return a 422 - validation error on account_holder_name: "Account holder name does not match bank account details provided". Testing instructions are [here](https://developer.gocardless.com/developer-tools/scenario-simulators/#payer_name_verification) ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `account_number` | string \| null | No | Bank account number - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `bank_code` | string \| null | No | Bank code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `branch_code` | string \| null | No | Branch code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `iban` | string \| null | No | International Bank Account Number. Alternatively you can provide [local details](#appendix-local-bank-details). IBANs are not accepted for Swedish bank accounts denominated in SEK - you must supply [local details](#local-bank-details-sweden). | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. The full name provided when the customer is created is stored and is available via the API, but is transliterated, upcased, and truncated to 18 characters in bank submissions. This field is required unless the request includes a [customer bank account token](#javascript-flow-customer-bank-account-tokens). | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `account_number_suffix` | string \| null | No | Account number suffix (only for bank accounts denominated in NZD) - see [local details](#local-bank-details-new-zealand) for more information. | | `pay_id` | string | No | A unique record such as an email address, mobile number or company number, that can be used to make and accept payments. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Confirm the payer details `POST /billing_requests/{billing_request_id}/actions/confirm_payer_details` This is needed when you have a mandate request. As a scheme compliance rule we are required to allow the payer to crosscheck the details entered by them and confirm it.

Restricted: this endpoint is restricted to [GoCardless Pro](https://gocardless.com/pricing) and [GoCardless Enterprise](https://gocardless.com/pricing) accounts with the [custom payment pages upgrade](https://hub.gocardless.com/s/article/Custom-payment-pages).

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `payer_requested_dual_signature` | boolean | No | This attribute can be set to true if the payer has indicated that multiple signatures are required for the mandate. As long as every other Billing Request actions have been completed, the payer will receive an email notification containing instructions on how to complete the additional signature. The dual signature flow can only be completed using GoCardless branded pages. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Fulfil a Billing Request `POST /billing_requests/{billing_request_id}/actions/fulfil` If a billing request is ready to be fulfilled, call this endpoint to cause it to fulfil, executing the payment. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Cancel a Billing Request `POST /billing_requests/{billing_request_id}/actions/cancel` Immediately cancels a billing request, causing all billing request flows to expire. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single Billing Request `GET /billing_requests/{billing_request_id}` Fetches a billing request ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Notify the customer `POST /billing_requests/{billing_request_id}/actions/notify` Notifies the customer linked to the billing request, asking them to authorise it. Currently, the customer can only be notified by email. This endpoint is currently supported only for Pay by Bank Billing Requests. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `notification_type` | enum | Yes | Currently, can only be `email`. | | `redirect_uri` | string | No | URL that the payer can be redirected to after authorising the payment. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Trigger fallback `POST /billing_requests/{billing_request_id}/actions/fallback` Triggers a fallback from the open-banking flow to direct debit. Note, the billing request must have fallback enabled.

Restricted: this endpoint is restricted to [GoCardless Pro](https://gocardless.com/pricing) and [GoCardless Enterprise](https://gocardless.com/pricing) accounts with the [custom payment pages upgrade](https://hub.gocardless.com/s/article/Custom-payment-pages).

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Change currency `POST /billing_requests/{billing_request_id}/actions/choose_currency` This will allow for the updating of the currency and subsequently the scheme if needed for a Billing Request. This will only be available for mandate only flows which do not have the lock_currency flag set to true on the Billing Request Flow. It will also not support any request which has a payments request. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `currency` | string \| null | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Select institution for a Billing Request `POST /billing_requests/{billing_request_id}/actions/select_institution` Creates an Institution object and attaches it to the Billing Request

Restricted: this endpoint is restricted to [GoCardless Pro](https://gocardless.com/pricing) and [GoCardless Enterprise](https://gocardless.com/pricing) accounts with the [custom payment pages upgrade](https://hub.gocardless.com/s/article/Custom-payment-pages).

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | ### Request body Wrap request body attributes in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `institution` | string | Yes | The unique identifier for this institution | | `country_code` | string | Yes | [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code. The country code of the institution. If nothing is provided, institutions with the country code 'GB' are returned by default. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_requests` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRQ". | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | One of: - `pending`: the billing request is pending and can be used - `ready_to_fulfil`: the billing request is ready to fulfil - `fulfilling`: the billing request is currently undergoing fulfilment - `fulfilled`: the billing request has been fulfilled and a payment created - `cancelled`: the billing request has been cancelled and cannot be used | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `mandate_request` | object \| null | No | Request for a mandate | | `payment_request` | object \| null | No | Request for a one-off strongly authorised payment | | `subscription_request` | object \| null | No | Request for a subscription | | `instalment_schedule_request` | object \| null | No | Request for an instalment schedule. Has to contain either `instalments_with_schedule` object or an array of `instalments_with_dates` objects | | `actions` | array | No | List of actions that can be performed before this billing request can be fulfilled. | | `resources` | object | No | | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `fallback_occurred` | boolean | No | True if the billing request was completed with direct debit. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## billing-request-flow URL: https://docs.gocardless.com/docs/api-reference/billing-request-flow # Billing Request Flow Source: https://docs.gocardless.com/docs/api-reference/billing-request-flow ## Create a Billing Request Flow `POST /billing_request_flows` Creates a new billing request flow. ### Request body Wrap request body attributes in a `billing_request_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `auto_fulfil` | boolean | No | (Experimental feature) Fulfil the Billing Request on completion of the flow (true by default). Disabling the auto_fulfil is not allowed currently. | | `customer_details_captured` | boolean | No | Identifies whether a Billing Request belongs to a specific customer | | `lock_bank_account` | boolean | No | If true, the payer will not be able to change their bank account within the flow. If the bank_account details are collected as part of bank_authorisation then GC will set this value to true mid flow. You can only lock bank account if these have already been completed as a part of the billing request. | | `lock_currency` | boolean | No | If true, the payer will not be able to change their currency/scheme manually within the flow. Note that this only applies to the mandate only flows - currency/scheme can never be changed when there is a specified subscription or payment. | | `lock_customer_details` | boolean | No | If true, the payer will not be able to edit their customer details within the flow. If the customer details are collected as part of bank_authorisation then GC will set this value to true mid flow. You can only lock customer details if these have already been completed as a part of the billing request. | | `show_redirect_buttons` | boolean | No | If true, the payer will be able to see redirect action buttons on Thank You page. These action buttons will provide a way to connect back to the billing request flow app if opened within a mobile app. For successful flow, the button will take the payer back the billing request flow where they will see the success screen. For failure, button will take the payer to url being provided against exit_uri field. | | `show_success_redirect_button` | boolean | No | If true, the payer will be able to see a redirect action button on the Success page. This action button will provide a way to redirect the payer to the given redirect_uri. This functionality is helpful when merchants do not want payers to be automatically redirected or on Android devices, where automatic redirections are not possible. | | `redirect_uri` | string \| null | No | URL that the payer can be redirected to after completing the request flow. | | `skip_success_screen` | boolean | No | If true, the payer will not be redirected to the success screen after completing the flow. A redirect_uri needs to be provided for this parameter to be taken into account. | | `exit_uri` | string \| null | No | URL that the payer can be taken to if there isn't a way to progress ahead in flow, for example if the customer searches for a bank that doesn't exist or isn't supported on the scheme. | | `prefilled_customer` | object \| null | No | Customer information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `prefilled_bank_account` | object \| null | No | Bank account information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `language` | string \| null | No | Sets the default language of the Billing Request Flow and the customer. [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_request_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRF". | | `redirect_uri` | string \| null | No | URL that the payer can be redirected to after completing the request flow. | | `skip_success_screen` | boolean | No | If true, the payer will not be redirected to the success screen after completing the flow. A redirect_uri needs to be provided for this parameter to be taken into account. | | `exit_uri` | string \| null | No | URL that the payer can be taken to if there isn't a way to progress ahead in flow, for example if the customer searches for a bank that doesn't exist or isn't supported on the scheme. | | `show_redirect_buttons` | boolean | No | If true, the payer will be able to see redirect action buttons on Thank You page. These action buttons will provide a way to connect back to the billing request flow app if opened within a mobile app. For successful flow, the button will take the payer back the billing request flow where they will see the success screen. For failure, button will take the payer to url being provided against exit_uri field. | | `show_success_redirect_button` | boolean | No | If true, the payer will be able to see a redirect action button on the Success page. This action button will provide a way to redirect the payer to the given redirect_uri. This functionality is helpful when merchants do not want payers to be automatically redirected or on Android devices, where automatic redirections are not possible. | | `authorisation_url` | string | No | URL for a GC-controlled flow which will allow the payer to fulfil the billing request | | `created_at` | string | No | Timestamp when the flow was created | | `expires_at` | string | No | Timestamp when the flow will expire. Each flow currently lasts for 7 days. | | `session_token` | string \| null | No | Session token populated when responding to the initialise action | | `auto_fulfil` | boolean | No | (Experimental feature) Fulfil the Billing Request on completion of the flow (true by default). Disabling the auto_fulfil is not allowed currently. | | `lock_bank_account` | boolean | No | If true, the payer will not be able to change their bank account within the flow. If the bank_account details are collected as part of bank_authorisation then GC will set this value to true mid flow. You can only lock bank account if these have already been completed as a part of the billing request. | | `lock_currency` | boolean | No | If true, the payer will not be able to change their currency/scheme manually within the flow. Note that this only applies to the mandate only flows - currency/scheme can never be changed when there is a specified subscription or payment. | | `lock_customer_details` | boolean | No | If true, the payer will not be able to edit their customer details within the flow. If the customer details are collected as part of bank_authorisation then GC will set this value to true mid flow. You can only lock customer details if these have already been completed as a part of the billing request. | | `prefilled_customer` | object \| null | No | Customer information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `prefilled_bank_account` | object \| null | No | Bank account information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `language` | string \| null | No | Sets the default language of the Billing Request Flow and the customer. [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. | | `links` | object | No | | | `customer_details_captured` | boolean | No | Identifies whether a Billing Request belongs to a specific customer | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Initialise a Billing Request Flow `POST /billing_request_flows/{billing_request_flow_id}/actions/initialise` Returns the flow having generated a fresh session token which can be used to power integrations that manipulate the flow. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_flow_id` | path | string | Yes | The billing request flow id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_request_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRF". | | `redirect_uri` | string \| null | No | URL that the payer can be redirected to after completing the request flow. | | `skip_success_screen` | boolean | No | If true, the payer will not be redirected to the success screen after completing the flow. A redirect_uri needs to be provided for this parameter to be taken into account. | | `exit_uri` | string \| null | No | URL that the payer can be taken to if there isn't a way to progress ahead in flow, for example if the customer searches for a bank that doesn't exist or isn't supported on the scheme. | | `show_redirect_buttons` | boolean | No | If true, the payer will be able to see redirect action buttons on Thank You page. These action buttons will provide a way to connect back to the billing request flow app if opened within a mobile app. For successful flow, the button will take the payer back the billing request flow where they will see the success screen. For failure, button will take the payer to url being provided against exit_uri field. | | `show_success_redirect_button` | boolean | No | If true, the payer will be able to see a redirect action button on the Success page. This action button will provide a way to redirect the payer to the given redirect_uri. This functionality is helpful when merchants do not want payers to be automatically redirected or on Android devices, where automatic redirections are not possible. | | `authorisation_url` | string | No | URL for a GC-controlled flow which will allow the payer to fulfil the billing request | | `created_at` | string | No | Timestamp when the flow was created | | `expires_at` | string | No | Timestamp when the flow will expire. Each flow currently lasts for 7 days. | | `session_token` | string \| null | No | Session token populated when responding to the initialise action | | `auto_fulfil` | boolean | No | (Experimental feature) Fulfil the Billing Request on completion of the flow (true by default). Disabling the auto_fulfil is not allowed currently. | | `lock_bank_account` | boolean | No | If true, the payer will not be able to change their bank account within the flow. If the bank_account details are collected as part of bank_authorisation then GC will set this value to true mid flow. You can only lock bank account if these have already been completed as a part of the billing request. | | `lock_currency` | boolean | No | If true, the payer will not be able to change their currency/scheme manually within the flow. Note that this only applies to the mandate only flows - currency/scheme can never be changed when there is a specified subscription or payment. | | `lock_customer_details` | boolean | No | If true, the payer will not be able to edit their customer details within the flow. If the customer details are collected as part of bank_authorisation then GC will set this value to true mid flow. You can only lock customer details if these have already been completed as a part of the billing request. | | `prefilled_customer` | object \| null | No | Customer information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `prefilled_bank_account` | object \| null | No | Bank account information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `language` | string \| null | No | Sets the default language of the Billing Request Flow and the customer. [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. | | `links` | object | No | | | `customer_details_captured` | boolean | No | Identifies whether a Billing Request belongs to a specific customer | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## billing-request-template URL: https://docs.gocardless.com/docs/api-reference/billing-request-template # Billing Request Template Source: https://docs.gocardless.com/docs/api-reference/billing-request-template ## List Billing Request Templates `GET /billing_request_templates` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your Billing Request Templates. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `payment_request_scheme` | query | string \| null | No | (Optional) A scheme used for Open Banking payments. Currently `faster_payments` is supported in the UK (GBP) and `sepa_credit_transfer` and `sepa_instant_credit_transfer` are supported in supported Eurozone countries (EUR). For Eurozone countries, `sepa_credit_transfer` is used as the default. Please be aware that `sepa_instant_credit_transfer` may incur an additional fee for your customer. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `billing_request_templates` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRT". | | `name` | string | Yes | Name for the template. Provides a friendly human name for the template, as it is shown in the dashboard. Must not exceed 255 characters. | | `mandate_request_currency` | | Yes | | | `mandate_request_scheme` | | Yes | | | `mandate_request_verify` | string \| null | Yes | Verification preference for the mandate. | | `mandate_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the mandate created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `payment_request_description` | | Yes | | | `mandate_request_description` | | Yes | | | `mandate_request_constraints` | | Yes | | | `payment_request_amount` | string \| null | Yes | Amount in full. | | `payment_request_currency` | | Yes | | | `payment_request_scheme` | | Yes | | | `payment_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the payment created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `redirect_uri` | | Yes | | | `authorisation_url` | string | Yes | Permanent URL that customers can visit to allow them to complete a flow based on this template, before being returned to the `redirect_uri`. | | `metadata` | | Yes | | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | Yes | Dynamic [timestamp](#api-usage-dates-and-times) recording when this resource was last updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Create a Billing Request Template `POST /billing_request_templates` ### Request body Wrap request body attributes in a `billing_request_templates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | No | Name for the template. Provides a friendly human name for the template, as it is shown in the dashboard. Must not exceed 255 characters. | | `mandate_request_currency` | | No | | | `mandate_request_scheme` | | No | | | `mandate_request_verify` | string \| null | No | Verification preference for the mandate. | | `mandate_request_metadata` | object \| null | No | Key-value store of custom data that will be applied to the mandate created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `payment_request_description` | | No | | | `mandate_request_description` | | No | | | `mandate_request_constraints` | | No | | | `payment_request_amount` | string \| null | No | Amount in full. | | `payment_request_currency` | | No | | | `payment_request_scheme` | | No | | | `payment_request_metadata` | object \| null | No | Key-value store of custom data that will be applied to the payment created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `redirect_uri` | | No | | | `metadata` | | No | | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_request_templates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRT". | | `name` | string | Yes | Name for the template. Provides a friendly human name for the template, as it is shown in the dashboard. Must not exceed 255 characters. | | `mandate_request_currency` | | Yes | | | `mandate_request_scheme` | | Yes | | | `mandate_request_verify` | string \| null | Yes | Verification preference for the mandate. | | `mandate_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the mandate created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `payment_request_description` | | Yes | | | `mandate_request_description` | | Yes | | | `mandate_request_constraints` | | Yes | | | `payment_request_amount` | string \| null | Yes | Amount in full. | | `payment_request_currency` | | Yes | | | `payment_request_scheme` | | Yes | | | `payment_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the payment created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `redirect_uri` | | Yes | | | `authorisation_url` | string | Yes | Permanent URL that customers can visit to allow them to complete a flow based on this template, before being returned to the `redirect_uri`. | | `metadata` | | Yes | | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | Yes | Dynamic [timestamp](#api-usage-dates-and-times) recording when this resource was last updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single Billing Request Template `GET /billing_request_templates/{billing_request_template_id}` Fetches a Billing Request Template ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_template_id` | path | string | Yes | The billing request template id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_request_templates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRT". | | `name` | string | Yes | Name for the template. Provides a friendly human name for the template, as it is shown in the dashboard. Must not exceed 255 characters. | | `mandate_request_currency` | | Yes | | | `mandate_request_scheme` | | Yes | | | `mandate_request_verify` | string \| null | Yes | Verification preference for the mandate. | | `mandate_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the mandate created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `payment_request_description` | | Yes | | | `mandate_request_description` | | Yes | | | `mandate_request_constraints` | | Yes | | | `payment_request_amount` | string \| null | Yes | Amount in full. | | `payment_request_currency` | | Yes | | | `payment_request_scheme` | | Yes | | | `payment_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the payment created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `redirect_uri` | | Yes | | | `authorisation_url` | string | Yes | Permanent URL that customers can visit to allow them to complete a flow based on this template, before being returned to the `redirect_uri`. | | `metadata` | | Yes | | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | Yes | Dynamic [timestamp](#api-usage-dates-and-times) recording when this resource was last updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a Billing Request Template `PUT /billing_request_templates/{billing_request_template_id}` Updates a Billing Request Template, which will affect all future Billing Requests created by this template. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_template_id` | path | string | Yes | The billing request template id | ### Request body Wrap request body attributes in a `billing_request_templates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | No | Name for the template. Provides a friendly human name for the template, as it is shown in the dashboard. Must not exceed 255 characters. | | `mandate_request_currency` | | No | | | `mandate_request_scheme` | | No | | | `mandate_request_verify` | string \| null | No | Verification preference for the mandate. | | `mandate_request_metadata` | object \| null | No | Key-value store of custom data that will be applied to the mandate created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `payment_request_description` | | No | | | `mandate_request_description` | | No | | | `mandate_request_constraints` | | No | | | `payment_request_amount` | string \| null | No | Amount in full. | | `payment_request_currency` | | No | | | `payment_request_scheme` | | No | | | `payment_request_metadata` | object \| null | No | Key-value store of custom data that will be applied to the payment created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `redirect_uri` | | No | | | `metadata` | | No | | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_request_templates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "BRT". | | `name` | string | Yes | Name for the template. Provides a friendly human name for the template, as it is shown in the dashboard. Must not exceed 255 characters. | | `mandate_request_currency` | | Yes | | | `mandate_request_scheme` | | Yes | | | `mandate_request_verify` | string \| null | Yes | Verification preference for the mandate. | | `mandate_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the mandate created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `payment_request_description` | | Yes | | | `mandate_request_description` | | Yes | | | `mandate_request_constraints` | | Yes | | | `payment_request_amount` | string \| null | Yes | Amount in full. | | `payment_request_currency` | | Yes | | | `payment_request_scheme` | | Yes | | | `payment_request_metadata` | object \| null | Yes | Key-value store of custom data that will be applied to the payment created when this request is fulfilled. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `redirect_uri` | | Yes | | | `authorisation_url` | string | Yes | Permanent URL that customers can visit to allow them to complete a flow based on this template, before being returned to the `redirect_uri`. | | `metadata` | | Yes | | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | Yes | Dynamic [timestamp](#api-usage-dates-and-times) recording when this resource was last updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## billing-request-with-action URL: https://docs.gocardless.com/docs/api-reference/billing-request-with-action # Billing Request With Action Source: https://docs.gocardless.com/docs/api-reference/billing-request-with-action ## Create a Billing Request with Actions `POST /billing_requests/create_with_actions` Creates a billing request and completes any specified actions in a single request. This endpoint allows you to create a billing request and immediately complete actions such as collecting customer details, bank account details, or other required actions.

Restricted: this endpoint is restricted to [GoCardless Pro](https://gocardless.com/pricing) and [GoCardless Enterprise](https://gocardless.com/pricing) accounts with the [custom payment pages upgrade](https://hub.gocardless.com/s/article/Custom-payment-pages).

Note: to modify data on an already created billing request, call individual action endpoints. Calling this endpoint creates a new billing request everytime.

Warning: ACH/PAD is not supported on this endpoint.

### Request body Wrap request body attributes in a `billing_request_with_actions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `mandate_request` | object | No | | | `payment_request` | object | No | | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `fallback_enabled` | boolean | No | (Optional) If true, this billing request can fallback from instant payment to direct debit. Should not be set if GoCardless payment intelligence feature is used. See [Billing Requests: Retain customers with Fallbacks](https://developer.gocardless.com/billing-requests/retain-customers-with-fallbacks/) for more information. | | `purpose_code` | enum | No | Specifies the high-level purpose/category of a mandate and/or payment using a set of pre-defined categories. Provides context on the nature and reason for the payment to facilitate processing and compliance. See [Billing Request Purpose Codes](https://developer.gocardless.com/billing-request-purpose-codes/) for the complete list of valid codes. | | `payment_purpose_code` | string | No | Specifies the underlying purpose of the payment. Defines the specific reason or type of service/goods the payment relates to, improving straight-through processing and compliance. See [VRP Commercial Payment Purpose Codes](https://developer.gocardless.com/vrp-commercial-payment-purpose-codes/) for the complete list of valid codes. | | `payment_context_code` | enum | No | Specifies the context or scenario in which the payment is being made. Defines whether the payment is for advance/arrears billing, point of sale transactions, ecommerce, or account transfers. This helps banks and payment processors understand the payment scenario and apply appropriate processing rules and risk controls. | | `actions` | object | No | Action payloads | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `billing_request_with_actions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `billing_requests` | object | Yes | Billing Requests help create resources that require input or action from a customer. An example of required input might be additional customer billing details, while an action would be asking a customer to authorise a payment using their mobile banking app. See [Billing Requests: Overview](https://developer.gocardless.com/getting-started/billing-requests/overview/) for how-to's, explanations and tutorials.

Important: All properties associated with `subscription_request` and `instalment_schedule_request` are only supported for ACH and PAD schemes.

| | `bank_authorisations` | object \| null | No | Bank authorisation resource, or null if no bank authorisation was created. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## block URL: https://docs.gocardless.com/docs/api-reference/block # Block Source: https://docs.gocardless.com/docs/api-reference/block ## Create a block `POST /blocks` Creates a new Block of a given type. By default it will be active.

Note: Block will be enabled if you try to create a block that already exists and is disabled.

### Request body Wrap request body attributes in a `blocks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `block_type` | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `resource_reference` | string | No | This field is a reference to the value you wish to block. This may be the raw value (in the case of emails or email domains) or the ID of the resource (in the case of bank accounts and bank names). This means in order to block a specific bank account (even if you wish to block generically by name) it must already have been created as a resource. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `blocks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BLC". | | `block_type` | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `resource_reference` | string | No | This field is a reference to the value you wish to block. This may be the raw value (in the case of emails or email domains) or the ID of the resource (in the case of bank accounts and bank names). This means in order to block a specific bank account (even if you wish to block generically by name) it must already have been created as a resource. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List multiple blocks `GET /blocks` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your blocks. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `block_type` | query | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | query | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `blocks` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BLC". | | `block_type` | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `resource_reference` | string | No | This field is a reference to the value you wish to block. This may be the raw value (in the case of emails or email domains) or the ID of the resource (in the case of bank accounts and bank names). This means in order to block a specific bank account (even if you wish to block generically by name) it must already have been created as a resource. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single block `GET /blocks/{block_id}` Retrieves the details of an existing block. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `block_id` | path | string | Yes | The block id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `blocks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BLC". | | `block_type` | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `resource_reference` | string | No | This field is a reference to the value you wish to block. This may be the raw value (in the case of emails or email domains) or the ID of the resource (in the case of bank accounts and bank names). This means in order to block a specific bank account (even if you wish to block generically by name) it must already have been created as a resource. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Disable a block `POST /blocks/{block_id}/actions/disable` Disables a block so that it no longer will prevent mandate creation. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `block_id` | path | string | Yes | The block id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `blocks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BLC". | | `block_type` | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `resource_reference` | string | No | This field is a reference to the value you wish to block. This may be the raw value (in the case of emails or email domains) or the ID of the resource (in the case of bank accounts and bank names). This means in order to block a specific bank account (even if you wish to block generically by name) it must already have been created as a resource. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Enable a block `POST /blocks/{block_id}/actions/enable` Enables a previously disabled block so that it will prevent mandate creation ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `block_id` | path | string | Yes | The block id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `blocks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BLC". | | `block_type` | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `resource_reference` | string | No | This field is a reference to the value you wish to block. This may be the raw value (in the case of emails or email domains) or the ID of the resource (in the case of bank accounts and bank names). This means in order to block a specific bank account (even if you wish to block generically by name) it must already have been created as a resource. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Create blocks by reference `POST /blocks/block_by_ref` Creates new blocks for a given reference. By default blocks will be active. Returns 201 if at least one block was created. Returns 200 if there were no new blocks created. ### Request body Wrap request body attributes in a `blocks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `reference_type` | enum | No | Type of entity we will seek to get the associated emails and bank accounts to create blocks from. This can currently be one of 'customer' or 'mandate'. | | `reference_value` | string | No | This field is a reference to the entity you wish to block based on its emails and bank accounts. This may be the ID of a customer or a mandate. This means in order to block by reference the entity must have already been created as a resource. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `blocks` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BLC". | | `block_type` | enum | No | Type of entity we will seek to match against when blocking the mandate. This can currently be one of 'email', 'email_domain', 'bank_account', or 'bank_name'. | | `reason_type` | enum | No | The reason you wish to block this payer, can currently be one of 'identity_fraud', 'no_intent_to_pay', 'unfair_chargeback'. If the reason isn't captured by one of the above then 'other' can be selected but you must provide a reason description. | | `reason_description` | string \| null | No | This field is required if the reason_type is other. It should be a description of the reason for why you wish to block this payer and why it does not align with the given reason_types. This is intended to help us improve our knowledge of types of fraud. | | `resource_reference` | string | No | This field is a reference to the value you wish to block. This may be the raw value (in the case of emails or email domains) or the ID of the resource (in the case of bank accounts and bank names). This means in order to block a specific bank account (even if you wish to block generically by name) it must already have been created as a resource. | | `active` | boolean \| null | No | Shows if the block is active or disabled. Only active blocks will be used when deciding if a mandate should be blocked. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `updated_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was updated. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## creditor URL: https://docs.gocardless.com/docs/api-reference/creditor # Creditor Source: https://docs.gocardless.com/docs/api-reference/creditor ## Create a creditor `POST /creditors` Creates a new creditor.

Restricted: This endpoint is restricted to GoCardless Embed customers. Please [contact us](https://forms.gocardless.com/l/305971/2023-01-25/535t8n){:target="_blank"} if you are interested in using this product. Partners should instead manage multiple merchant accounts by building a [partner integration](https://developer.gocardless.com/getting-started/partners/introduction/).

### Request body Wrap request body attributes in a `creditors` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | The creditor's trading name. | | `country_code` | string \| null | Yes | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `creditor_type` | enum \| null | Yes | The type of business of the creditor. Currently, `individual`, `company`, `charity`, `partnership`, and `trust` are supported. | | `bank_reference_prefix` | string | No | Prefix for the bank reference of payouts sent to this creditor. For instance, if the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a payout sent to that creditor could be `ACME-8G7Q8`. This prefix is also used for refunds in EUR and GBP. | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `creditors` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CR". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `name` | string | No | The creditor's trading name. | | `address_line1` | string \| null | No | The first line of the creditor's address. | | `address_line2` | string \| null | No | The second line of the creditor's address. | | `address_line3` | string \| null | No | The third line of the creditor's address. | | `city` | string \| null | No | The city of the creditor's address. | | `region` | string \| null | No | The creditor's address region, county or department. | | `postal_code` | string \| null | No | The creditor's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `can_create_refunds` | boolean | No | Boolean indicating whether the creditor is permitted to create refunds. | | `bank_reference_prefix` | string | No | Prefix for the bank reference of payouts sent to this creditor. For instance, if the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a payout sent to that creditor could be `ACME-8G7Q8`. This prefix is also used for refunds in EUR and GBP. | | `links` | object | No | | | `scheme_identifiers` | array | No | An array of the scheme identifiers this creditor can create mandates against. The support address, `phone_number` and `email` fields are for customers to contact the merchant for support purposes. They must be displayed on the payment page, please see our [compliance requirements](#appendix-compliance-requirements) for more details. | | `logo_url` | string \| null | No | URL for the creditor's logo, which may be shown on their payment pages. | | `verification_status` | enum | No | The creditor's verification status, indicating whether they can yet receive payouts. For more details on handling verification as a partner, see our ["Helping your users get verified" guide](/getting-started/partners/helping-your-users-get-verified/). One of: - `successful`: The creditor's account is fully verified, and they can receive payouts. Once a creditor has been successfully verified, they may in the future require further verification - for example, if they change their payout bank account, we will have to check that they own the new bank account before they can receive payouts again. - `in_review`: The creditor has provided all of the information currently requested, and it is awaiting review by GoCardless before they can be verified and receive payouts. - `action_required`: The creditor needs to provide further information to verify their account so they can receive payouts, and should visit the verification flow. | | `merchant_responsible_for_notifications` | boolean | No | Boolean value indicating whether the organisation is responsible for sending all customer notifications (note this is separate from the functionality described [here](/getting-started/api/handling-customer-notifications/)). If you are a partner app, and this value is true, you should not send notifications on behalf of this organisation. | | `mandate_imports_enabled` | boolean | No | Boolean value indicating whether creditor has the [Mandate Imports](#core-endpoints-mandate-imports) functionality enabled. | | `custom_payment_pages_enabled` | boolean | No | Boolean value indicating whether creditor has the [Custom Payment Pages](https://hub.gocardless.com/s/article/Custom-payment-pages) functionality enabled. | | `fx_payout_currency` | enum \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) code for the currency in which amounts will be paid out (after foreign exchange). Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. Present only if payouts will be (or were) made via foreign exchange. | | `creditor_type` | enum \| null | No | The type of business of the creditor. Currently, `individual`, `company`, `charity`, `partnership`, and `trust` are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List creditors `GET /creditors` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your creditors. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `creditors` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CR". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `name` | string | No | The creditor's trading name. | | `address_line1` | string \| null | No | The first line of the creditor's address. | | `address_line2` | string \| null | No | The second line of the creditor's address. | | `address_line3` | string \| null | No | The third line of the creditor's address. | | `city` | string \| null | No | The city of the creditor's address. | | `region` | string \| null | No | The creditor's address region, county or department. | | `postal_code` | string \| null | No | The creditor's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `can_create_refunds` | boolean | No | Boolean indicating whether the creditor is permitted to create refunds. | | `bank_reference_prefix` | string | No | Prefix for the bank reference of payouts sent to this creditor. For instance, if the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a payout sent to that creditor could be `ACME-8G7Q8`. This prefix is also used for refunds in EUR and GBP. | | `links` | object | No | | | `scheme_identifiers` | array | No | An array of the scheme identifiers this creditor can create mandates against. The support address, `phone_number` and `email` fields are for customers to contact the merchant for support purposes. They must be displayed on the payment page, please see our [compliance requirements](#appendix-compliance-requirements) for more details. | | `logo_url` | string \| null | No | URL for the creditor's logo, which may be shown on their payment pages. | | `verification_status` | enum | No | The creditor's verification status, indicating whether they can yet receive payouts. For more details on handling verification as a partner, see our ["Helping your users get verified" guide](/getting-started/partners/helping-your-users-get-verified/). One of: - `successful`: The creditor's account is fully verified, and they can receive payouts. Once a creditor has been successfully verified, they may in the future require further verification - for example, if they change their payout bank account, we will have to check that they own the new bank account before they can receive payouts again. - `in_review`: The creditor has provided all of the information currently requested, and it is awaiting review by GoCardless before they can be verified and receive payouts. - `action_required`: The creditor needs to provide further information to verify their account so they can receive payouts, and should visit the verification flow. | | `merchant_responsible_for_notifications` | boolean | No | Boolean value indicating whether the organisation is responsible for sending all customer notifications (note this is separate from the functionality described [here](/getting-started/api/handling-customer-notifications/)). If you are a partner app, and this value is true, you should not send notifications on behalf of this organisation. | | `mandate_imports_enabled` | boolean | No | Boolean value indicating whether creditor has the [Mandate Imports](#core-endpoints-mandate-imports) functionality enabled. | | `custom_payment_pages_enabled` | boolean | No | Boolean value indicating whether creditor has the [Custom Payment Pages](https://hub.gocardless.com/s/article/Custom-payment-pages) functionality enabled. | | `fx_payout_currency` | enum \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) code for the currency in which amounts will be paid out (after foreign exchange). Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. Present only if payouts will be (or were) made via foreign exchange. | | `creditor_type` | enum \| null | No | The type of business of the creditor. Currently, `individual`, `company`, `charity`, `partnership`, and `trust` are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single creditor `GET /creditors/{creditor_id}` Retrieves the details of an existing creditor. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `creditor_id` | path | string | Yes | The creditor id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `creditors` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CR". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `name` | string | No | The creditor's trading name. | | `address_line1` | string \| null | No | The first line of the creditor's address. | | `address_line2` | string \| null | No | The second line of the creditor's address. | | `address_line3` | string \| null | No | The third line of the creditor's address. | | `city` | string \| null | No | The city of the creditor's address. | | `region` | string \| null | No | The creditor's address region, county or department. | | `postal_code` | string \| null | No | The creditor's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `can_create_refunds` | boolean | No | Boolean indicating whether the creditor is permitted to create refunds. | | `bank_reference_prefix` | string | No | Prefix for the bank reference of payouts sent to this creditor. For instance, if the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a payout sent to that creditor could be `ACME-8G7Q8`. This prefix is also used for refunds in EUR and GBP. | | `links` | object | No | | | `scheme_identifiers` | array | No | An array of the scheme identifiers this creditor can create mandates against. The support address, `phone_number` and `email` fields are for customers to contact the merchant for support purposes. They must be displayed on the payment page, please see our [compliance requirements](#appendix-compliance-requirements) for more details. | | `logo_url` | string \| null | No | URL for the creditor's logo, which may be shown on their payment pages. | | `verification_status` | enum | No | The creditor's verification status, indicating whether they can yet receive payouts. For more details on handling verification as a partner, see our ["Helping your users get verified" guide](/getting-started/partners/helping-your-users-get-verified/). One of: - `successful`: The creditor's account is fully verified, and they can receive payouts. Once a creditor has been successfully verified, they may in the future require further verification - for example, if they change their payout bank account, we will have to check that they own the new bank account before they can receive payouts again. - `in_review`: The creditor has provided all of the information currently requested, and it is awaiting review by GoCardless before they can be verified and receive payouts. - `action_required`: The creditor needs to provide further information to verify their account so they can receive payouts, and should visit the verification flow. | | `merchant_responsible_for_notifications` | boolean | No | Boolean value indicating whether the organisation is responsible for sending all customer notifications (note this is separate from the functionality described [here](/getting-started/api/handling-customer-notifications/)). If you are a partner app, and this value is true, you should not send notifications on behalf of this organisation. | | `mandate_imports_enabled` | boolean | No | Boolean value indicating whether creditor has the [Mandate Imports](#core-endpoints-mandate-imports) functionality enabled. | | `custom_payment_pages_enabled` | boolean | No | Boolean value indicating whether creditor has the [Custom Payment Pages](https://hub.gocardless.com/s/article/Custom-payment-pages) functionality enabled. | | `fx_payout_currency` | enum \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) code for the currency in which amounts will be paid out (after foreign exchange). Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. Present only if payouts will be (or were) made via foreign exchange. | | `creditor_type` | enum \| null | No | The type of business of the creditor. Currently, `individual`, `company`, `charity`, `partnership`, and `trust` are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a creditor `PUT /creditors/{creditor_id}` Updates a creditor object. Supports all of the fields supported when creating a creditor. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `creditor_id` | path | string | Yes | The creditor id | ### Request body Wrap request body attributes in a `creditors` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | No | The creditor's trading name. | | `address_line1` | string \| null | No | The first line of the creditor's address. | | `address_line2` | string \| null | No | The second line of the creditor's address. | | `address_line3` | string \| null | No | The third line of the creditor's address. | | `city` | string \| null | No | The city of the creditor's address. | | `region` | string \| null | No | The creditor's address region, county or department. | | `postal_code` | string \| null | No | The creditor's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `bank_reference_prefix` | string | No | Prefix for the bank reference of payouts sent to this creditor. For instance, if the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a payout sent to that creditor could be `ACME-8G7Q8`. This prefix is also used for refunds in EUR and GBP. | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `creditors` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CR". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `name` | string | No | The creditor's trading name. | | `address_line1` | string \| null | No | The first line of the creditor's address. | | `address_line2` | string \| null | No | The second line of the creditor's address. | | `address_line3` | string \| null | No | The third line of the creditor's address. | | `city` | string \| null | No | The city of the creditor's address. | | `region` | string \| null | No | The creditor's address region, county or department. | | `postal_code` | string \| null | No | The creditor's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `can_create_refunds` | boolean | No | Boolean indicating whether the creditor is permitted to create refunds. | | `bank_reference_prefix` | string | No | Prefix for the bank reference of payouts sent to this creditor. For instance, if the creditor's `bank_reference_prefix` was `ACME`, the bank reference of a payout sent to that creditor could be `ACME-8G7Q8`. This prefix is also used for refunds in EUR and GBP. | | `links` | object | No | | | `scheme_identifiers` | array | No | An array of the scheme identifiers this creditor can create mandates against. The support address, `phone_number` and `email` fields are for customers to contact the merchant for support purposes. They must be displayed on the payment page, please see our [compliance requirements](#appendix-compliance-requirements) for more details. | | `logo_url` | string \| null | No | URL for the creditor's logo, which may be shown on their payment pages. | | `verification_status` | enum | No | The creditor's verification status, indicating whether they can yet receive payouts. For more details on handling verification as a partner, see our ["Helping your users get verified" guide](/getting-started/partners/helping-your-users-get-verified/). One of: - `successful`: The creditor's account is fully verified, and they can receive payouts. Once a creditor has been successfully verified, they may in the future require further verification - for example, if they change their payout bank account, we will have to check that they own the new bank account before they can receive payouts again. - `in_review`: The creditor has provided all of the information currently requested, and it is awaiting review by GoCardless before they can be verified and receive payouts. - `action_required`: The creditor needs to provide further information to verify their account so they can receive payouts, and should visit the verification flow. | | `merchant_responsible_for_notifications` | boolean | No | Boolean value indicating whether the organisation is responsible for sending all customer notifications (note this is separate from the functionality described [here](/getting-started/api/handling-customer-notifications/)). If you are a partner app, and this value is true, you should not send notifications on behalf of this organisation. | | `mandate_imports_enabled` | boolean | No | Boolean value indicating whether creditor has the [Mandate Imports](#core-endpoints-mandate-imports) functionality enabled. | | `custom_payment_pages_enabled` | boolean | No | Boolean value indicating whether creditor has the [Custom Payment Pages](https://hub.gocardless.com/s/article/Custom-payment-pages) functionality enabled. | | `fx_payout_currency` | enum \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) code for the currency in which amounts will be paid out (after foreign exchange). Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. Present only if payouts will be (or were) made via foreign exchange. | | `creditor_type` | enum \| null | No | The type of business of the creditor. Currently, `individual`, `company`, `charity`, `partnership`, and `trust` are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## creditor-bank-account URL: https://docs.gocardless.com/docs/api-reference/creditor-bank-account # Creditor Bank Account Source: https://docs.gocardless.com/docs/api-reference/creditor-bank-account ## Create a creditor bank account `POST /creditor_bank_accounts` Creates a new creditor bank account object. ### Request body Wrap request body attributes in a `creditor_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `account_number` | string \| null | No | Bank account number - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `bank_code` | string \| null | No | Bank code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `branch_code` | string \| null | No | Branch code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `iban` | string \| null | No | International Bank Account Number. Alternatively you can provide [local details](#appendix-local-bank-details). IBANs are not accepted for Swedish bank accounts denominated in SEK - you must supply [local details](#local-bank-details-sweden). | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `account_holder_name` | string | Yes | Name of the account holder, as known by the bank. Usually this is the same as the name stored with the linked [creditor](#core-endpoints-creditors). This field will be transliterated, upcased and truncated to 18 characters. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `set_as_default_payout_account` | boolean | No | Defaults to `true`. When this is set to `true`, it will cause this bank account to be set as the account that GoCardless will pay out to. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `creditor_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. Usually this is the same as the name stored with the linked [creditor](#core-endpoints-creditors). This field will be transliterated, upcased and truncated to 18 characters. | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `verification_status` | enum | No | Verification status of the Bank Account. Can be one of `pending`, `in_review` or `successful` | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List creditor bank accounts `GET /creditor_bank_accounts` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your creditor bank accounts. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `creditor` | query | string | No | Unique identifier, beginning with "CR". | | `enabled` | query | | No | If `true`, only return enabled bank accounts. If `false`, only return disabled bank accounts. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `creditor_bank_accounts` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. Usually this is the same as the name stored with the linked [creditor](#core-endpoints-creditors). This field will be transliterated, upcased and truncated to 18 characters. | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `verification_status` | enum | No | Verification status of the Bank Account. Can be one of `pending`, `in_review` or `successful` | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single creditor bank account `GET /creditor_bank_accounts/{creditor_bank_account_id}` Retrieves the details of an existing creditor bank account. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `creditor_bank_account_id` | path | string | Yes | The creditor bank account id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `creditor_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. Usually this is the same as the name stored with the linked [creditor](#core-endpoints-creditors). This field will be transliterated, upcased and truncated to 18 characters. | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `verification_status` | enum | No | Verification status of the Bank Account. Can be one of `pending`, `in_review` or `successful` | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Disable a creditor bank account `POST /creditor_bank_accounts/{creditor_bank_account_id}/actions/disable` Immediately disables the bank account, no money can be paid out to a disabled account. This will return a `disable_failed` error if the bank account has already been disabled. A disabled bank account can be re-enabled by creating a new bank account resource with the same details. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `creditor_bank_account_id` | path | string | Yes | The creditor bank account id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `creditor_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. Usually this is the same as the name stored with the linked [creditor](#core-endpoints-creditors). This field will be transliterated, upcased and truncated to 18 characters. | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `verification_status` | enum | No | Verification status of the Bank Account. Can be one of `pending`, `in_review` or `successful` | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## currency-exchange-rate URL: https://docs.gocardless.com/docs/api-reference/currency-exchange-rate # Currency Exchange Rate Source: https://docs.gocardless.com/docs/api-reference/currency-exchange-rate ## List exchange rates `GET /currency_exchange_rates` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of all exchange rates. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `source` | query | string | No | Source currency | | `target` | query | string | No | Target currency | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `currency_exchange_rates` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `source` | string | Yes | Source currency | | `target` | string | Yes | Target currency | | `rate` | string | Yes | The exchange rate from the source to target currencies provided with up to 10 decimal places. | | `time` | string | Yes | Time at which the rate was retrieved from the provider. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## customer URL: https://docs.gocardless.com/docs/api-reference/customer # Customer Source: https://docs.gocardless.com/docs/api-reference/customer ## Create a customer `POST /customers` Creates a new customer object.

Restricted: this endpoint is [restricted](#overview-restrictions) to [GoCardless Pro](https://gocardless.com/pricing) and [GoCardless Enterprise](https://gocardless.com/pricing) accounts with approved payment pages.

Warning: this endpoint is a legacy API endpoint and does not support GoCardless' newest features. We recommend using the [Billing Requests API](/billing-requests/overview) instead.

### Request body Wrap request body attributes in a `customers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `email` | string \| null | No | Customer's email address. Required in most cases, as this allows GoCardless to send notifications to this customer. | | `given_name` | string \| null | No | Customer's first name. Required unless a `company_name` is provided. | | `family_name` | string \| null | No | Customer's surname. Required unless a `company_name` is provided. | | `company_name` | string \| null | No | Customer's company name. Required unless a `given_name` and `family_name` are provided. For Canadian customers, the use of a `company_name` value will mean that any mandate created from this customer will be considered to be a "Business PAD" (otherwise, any mandate will be considered to be a "Personal PAD"). | | `address_line1` | string \| null | No | The first line of the customer's address. | | `address_line2` | string \| null | No | The second line of the customer's address. | | `address_line3` | string \| null | No | The third line of the customer's address. | | `city` | string \| null | No | The city of the customer's address. | | `region` | string \| null | No | The customer's address region, county or department. For US customers a 2 letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code is required (e.g. `CA` for California). | | `postal_code` | string \| null | No | The customer's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `language` | string \| null | No | [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used as the language for notification emails sent by GoCardless if your organisation does not send its own (see [compliance requirements](#appendix-compliance-requirements)). Currently only "en", "fr", "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this is not provided, the language will be chosen based on the `country_code` (if supplied) or default to "en". | | `phone_number` | string \| null | No | [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, including country code. | | `swedish_identity_number` | string \| null | No | For Swedish customers only. The civic/company number (personnummer, samordningsnummer, or organisationsnummer) of the customer. Must be supplied if the customer's bank account is denominated in Swedish krona (SEK). This field cannot be changed once it has been set. | | `danish_identity_number` | string \| null | No | For Danish customers only. The civic/company number (CPR or CVR) of the customer. Must be supplied if the customer's bank account is denominated in Danish krone (DKK). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CU". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `email` | string \| null | No | Customer's email address. Required in most cases, as this allows GoCardless to send notifications to this customer. | | `given_name` | string \| null | No | Customer's first name. Required unless a `company_name` is provided. | | `family_name` | string \| null | No | Customer's surname. Required unless a `company_name` is provided. | | `company_name` | string \| null | No | Customer's company name. Required unless a `given_name` and `family_name` are provided. For Canadian customers, the use of a `company_name` value will mean that any mandate created from this customer will be considered to be a "Business PAD" (otherwise, any mandate will be considered to be a "Personal PAD"). | | `address_line1` | string \| null | No | The first line of the customer's address. | | `address_line2` | string \| null | No | The second line of the customer's address. | | `address_line3` | string \| null | No | The third line of the customer's address. | | `city` | string \| null | No | The city of the customer's address. | | `region` | string \| null | No | The customer's address region, county or department. For US customers a 2 letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code is required (e.g. `CA` for California). | | `postal_code` | string \| null | No | The customer's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `language` | string \| null | No | [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used as the language for notification emails sent by GoCardless if your organisation does not send its own (see [compliance requirements](#appendix-compliance-requirements)). Currently only "en", "fr", "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this is not provided, the language will be chosen based on the `country_code` (if supplied) or default to "en". | | `phone_number` | string \| null | No | [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, including country code. | | `swedish_identity_number` | string \| null | No | For Swedish customers only. The civic/company number (personnummer, samordningsnummer, or organisationsnummer) of the customer. Must be supplied if the customer's bank account is denominated in Swedish krona (SEK). This field cannot be changed once it has been set. | | `danish_identity_number` | string \| null | No | For Danish customers only. The civic/company number (CPR or CVR) of the customer. Must be supplied if the customer's bank account is denominated in Danish krone (DKK). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List customers `GET /customers` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your customers. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `sort_field` | query | enum | No | Field by which to sort records. One of: - `name` - `company_name` - `created_at` | | `sort_direction` | query | enum | No | The direction to sort in. One of: - `asc` - `desc` | | `currency` | query | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `action_required` | query | enum | No | Boolean indicating whether the customer has any actions required. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `customers` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CU". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `email` | string \| null | No | Customer's email address. Required in most cases, as this allows GoCardless to send notifications to this customer. | | `given_name` | string \| null | No | Customer's first name. Required unless a `company_name` is provided. | | `family_name` | string \| null | No | Customer's surname. Required unless a `company_name` is provided. | | `company_name` | string \| null | No | Customer's company name. Required unless a `given_name` and `family_name` are provided. For Canadian customers, the use of a `company_name` value will mean that any mandate created from this customer will be considered to be a "Business PAD" (otherwise, any mandate will be considered to be a "Personal PAD"). | | `address_line1` | string \| null | No | The first line of the customer's address. | | `address_line2` | string \| null | No | The second line of the customer's address. | | `address_line3` | string \| null | No | The third line of the customer's address. | | `city` | string \| null | No | The city of the customer's address. | | `region` | string \| null | No | The customer's address region, county or department. For US customers a 2 letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code is required (e.g. `CA` for California). | | `postal_code` | string \| null | No | The customer's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `language` | string \| null | No | [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used as the language for notification emails sent by GoCardless if your organisation does not send its own (see [compliance requirements](#appendix-compliance-requirements)). Currently only "en", "fr", "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this is not provided, the language will be chosen based on the `country_code` (if supplied) or default to "en". | | `phone_number` | string \| null | No | [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, including country code. | | `swedish_identity_number` | string \| null | No | For Swedish customers only. The civic/company number (personnummer, samordningsnummer, or organisationsnummer) of the customer. Must be supplied if the customer's bank account is denominated in Swedish krona (SEK). This field cannot be changed once it has been set. | | `danish_identity_number` | string \| null | No | For Danish customers only. The civic/company number (CPR or CVR) of the customer. Must be supplied if the customer's bank account is denominated in Danish krone (DKK). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single customer `GET /customers/{customer_id}` Retrieves the details of an existing customer. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_id` | path | string | Yes | The customer id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CU". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `email` | string \| null | No | Customer's email address. Required in most cases, as this allows GoCardless to send notifications to this customer. | | `given_name` | string \| null | No | Customer's first name. Required unless a `company_name` is provided. | | `family_name` | string \| null | No | Customer's surname. Required unless a `company_name` is provided. | | `company_name` | string \| null | No | Customer's company name. Required unless a `given_name` and `family_name` are provided. For Canadian customers, the use of a `company_name` value will mean that any mandate created from this customer will be considered to be a "Business PAD" (otherwise, any mandate will be considered to be a "Personal PAD"). | | `address_line1` | string \| null | No | The first line of the customer's address. | | `address_line2` | string \| null | No | The second line of the customer's address. | | `address_line3` | string \| null | No | The third line of the customer's address. | | `city` | string \| null | No | The city of the customer's address. | | `region` | string \| null | No | The customer's address region, county or department. For US customers a 2 letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code is required (e.g. `CA` for California). | | `postal_code` | string \| null | No | The customer's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `language` | string \| null | No | [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used as the language for notification emails sent by GoCardless if your organisation does not send its own (see [compliance requirements](#appendix-compliance-requirements)). Currently only "en", "fr", "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this is not provided, the language will be chosen based on the `country_code` (if supplied) or default to "en". | | `phone_number` | string \| null | No | [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, including country code. | | `swedish_identity_number` | string \| null | No | For Swedish customers only. The civic/company number (personnummer, samordningsnummer, or organisationsnummer) of the customer. Must be supplied if the customer's bank account is denominated in Swedish krona (SEK). This field cannot be changed once it has been set. | | `danish_identity_number` | string \| null | No | For Danish customers only. The civic/company number (CPR or CVR) of the customer. Must be supplied if the customer's bank account is denominated in Danish krone (DKK). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a customer `PUT /customers/{customer_id}` Updates a customer object. Supports all of the fields supported when creating a customer. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_id` | path | string | Yes | The customer id | ### Request body Wrap request body attributes in a `customers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `email` | string \| null | No | Customer's email address. Required in most cases, as this allows GoCardless to send notifications to this customer. | | `given_name` | string \| null | No | Customer's first name. Required unless a `company_name` is provided. | | `family_name` | string \| null | No | Customer's surname. Required unless a `company_name` is provided. | | `company_name` | string \| null | No | Customer's company name. Required unless a `given_name` and `family_name` are provided. For Canadian customers, the use of a `company_name` value will mean that any mandate created from this customer will be considered to be a "Business PAD" (otherwise, any mandate will be considered to be a "Personal PAD"). | | `address_line1` | string \| null | No | The first line of the customer's address. | | `address_line2` | string \| null | No | The second line of the customer's address. | | `address_line3` | string \| null | No | The third line of the customer's address. | | `city` | string \| null | No | The city of the customer's address. | | `region` | string \| null | No | The customer's address region, county or department. For US customers a 2 letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code is required (e.g. `CA` for California). | | `postal_code` | string \| null | No | The customer's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `language` | string \| null | No | [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used as the language for notification emails sent by GoCardless if your organisation does not send its own (see [compliance requirements](#appendix-compliance-requirements)). Currently only "en", "fr", "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this is not provided, the language will be chosen based on the `country_code` (if supplied) or default to "en". | | `phone_number` | string \| null | No | [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, including country code. | | `swedish_identity_number` | string \| null | No | For Swedish customers only. The civic/company number (personnummer, samordningsnummer, or organisationsnummer) of the customer. Must be supplied if the customer's bank account is denominated in Swedish krona (SEK). This field cannot be changed once it has been set. | | `danish_identity_number` | string \| null | No | For Danish customers only. The civic/company number (CPR or CVR) of the customer. Must be supplied if the customer's bank account is denominated in Danish krone (DKK). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "CU". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `email` | string \| null | No | Customer's email address. Required in most cases, as this allows GoCardless to send notifications to this customer. | | `given_name` | string \| null | No | Customer's first name. Required unless a `company_name` is provided. | | `family_name` | string \| null | No | Customer's surname. Required unless a `company_name` is provided. | | `company_name` | string \| null | No | Customer's company name. Required unless a `given_name` and `family_name` are provided. For Canadian customers, the use of a `company_name` value will mean that any mandate created from this customer will be considered to be a "Business PAD" (otherwise, any mandate will be considered to be a "Personal PAD"). | | `address_line1` | string \| null | No | The first line of the customer's address. | | `address_line2` | string \| null | No | The second line of the customer's address. | | `address_line3` | string \| null | No | The third line of the customer's address. | | `city` | string \| null | No | The city of the customer's address. | | `region` | string \| null | No | The customer's address region, county or department. For US customers a 2 letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code is required (e.g. `CA` for California). | | `postal_code` | string \| null | No | The customer's postal code. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `language` | string \| null | No | [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code. Used as the language for notification emails sent by GoCardless if your organisation does not send its own (see [compliance requirements](#appendix-compliance-requirements)). Currently only "en", "fr", "de", "pt", "es", "it", "nl", "da", "nb", "sl", "sv" are supported. If this is not provided, the language will be chosen based on the `country_code` (if supplied) or default to "en". | | `phone_number` | string \| null | No | [ITU E.123](https://en.wikipedia.org/wiki/E.123) formatted phone number, including country code. | | `swedish_identity_number` | string \| null | No | For Swedish customers only. The civic/company number (personnummer, samordningsnummer, or organisationsnummer) of the customer. Must be supplied if the customer's bank account is denominated in Swedish krona (SEK). This field cannot be changed once it has been set. | | `danish_identity_number` | string \| null | No | For Danish customers only. The civic/company number (CPR or CVR) of the customer. Must be supplied if the customer's bank account is denominated in Danish krone (DKK). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Remove a customer `DELETE /customers/{customer_id}` Removed customers will not appear in search results or lists of customers (in our API or exports), and it will not be possible to load an individually removed customer by ID.

The action of removing a customer cannot be reversed, so please use with care.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_id` | path | string | Yes | The customer id | ### Responses | Status | Description | | --- | --- | | 204 | Resource deleted successfully (no content) | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## customer-bank-account URL: https://docs.gocardless.com/docs/api-reference/customer-bank-account # Customer Bank Account Source: https://docs.gocardless.com/docs/api-reference/customer-bank-account ## Create a customer bank account `POST /customer_bank_accounts` Creates a new customer bank account object. There are three different ways to supply bank account details: - [Local details](#appendix-local-bank-details) - IBAN - [Customer Bank Account Tokens](#javascript-flow-create-a-customer-bank-account-token) For more information on the different fields required in each country, see [local bank details](#appendix-local-bank-details).

Restricted: this endpoint requires approved [custom payment pages](https://support.gocardless.com/hc/en-gb/articles/115004521925-Custom-Payment-Pages).

Note: this endpoint is a legacy API endpoint and does not support GoCardless' newest features. We recommend using the [Billing Requests API](/billing-requests/overview) instead.

### Request body Wrap request body attributes in a `customer_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `account_number` | string \| null | No | Bank account number - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `bank_code` | string \| null | No | Bank code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `branch_code` | string \| null | No | Branch code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `iban` | string \| null | No | International Bank Account Number. Alternatively you can provide [local details](#appendix-local-bank-details). IBANs are not accepted for Swedish bank accounts denominated in SEK - you must supply [local details](#local-bank-details-sweden). | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. The full name provided when the customer is created is stored and is available via the API, but is transliterated, upcased, and truncated to 18 characters in bank submissions. This field is required unless the request includes a [customer bank account token](#javascript-flow-customer-bank-account-tokens). | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customer_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. The full name provided when the customer is created is stored and is available via the API, but is transliterated, upcased, and truncated to 18 characters in bank submissions. This field is required unless the request includes a [customer bank account token](#javascript-flow-customer-bank-account-tokens). | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `bank_account_token` | string \| null | No | A token to uniquely refer to a set of bank account details. This feature is still in early access and is only available for certain organisations. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `trusted_recipient` | boolean | No | Whether this customer bank account is registered as a trusted recipient for Outbound Payments. Only present when the feature is enabled for the organisation. | | `payer_name_verification_result` | enum | No | The result of the payer name verification check performed when the bank account was created. Only present if a check was performed. - `full`: The name provided matches the name held by the bank. - `close`: The name provided is a close but not exact match to the name held by the bank. - `cannot_perform_verification`: A verification was attempted but could not be completed. This can happen for a number of reasons, including the account holder's bank not participating in the verification scheme, the account not being eligible for verification (e.g. the account holder has opted out), or the bank details not being resolvable, among others. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List customer bank accounts `GET /customer_bank_accounts` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your bank accounts. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `customer` | query | string | No | Unique identifier, beginning with "CU". | | `enabled` | query | | No | Get enabled or disabled customer bank accounts. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `customer_bank_accounts` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. The full name provided when the customer is created is stored and is available via the API, but is transliterated, upcased, and truncated to 18 characters in bank submissions. This field is required unless the request includes a [customer bank account token](#javascript-flow-customer-bank-account-tokens). | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `bank_account_token` | string \| null | No | A token to uniquely refer to a set of bank account details. This feature is still in early access and is only available for certain organisations. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `trusted_recipient` | boolean | No | Whether this customer bank account is registered as a trusted recipient for Outbound Payments. Only present when the feature is enabled for the organisation. | | `payer_name_verification_result` | enum | No | The result of the payer name verification check performed when the bank account was created. Only present if a check was performed. - `full`: The name provided matches the name held by the bank. - `close`: The name provided is a close but not exact match to the name held by the bank. - `cannot_perform_verification`: A verification was attempted but could not be completed. This can happen for a number of reasons, including the account holder's bank not participating in the verification scheme, the account not being eligible for verification (e.g. the account holder has opted out), or the bank details not being resolvable, among others. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single customer bank account `GET /customer_bank_accounts/{customer_bank_account_id}` Retrieves the details of an existing bank account. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_bank_account_id` | path | string | Yes | The customer bank account id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customer_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. The full name provided when the customer is created is stored and is available via the API, but is transliterated, upcased, and truncated to 18 characters in bank submissions. This field is required unless the request includes a [customer bank account token](#javascript-flow-customer-bank-account-tokens). | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `bank_account_token` | string \| null | No | A token to uniquely refer to a set of bank account details. This feature is still in early access and is only available for certain organisations. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `trusted_recipient` | boolean | No | Whether this customer bank account is registered as a trusted recipient for Outbound Payments. Only present when the feature is enabled for the organisation. | | `payer_name_verification_result` | enum | No | The result of the payer name verification check performed when the bank account was created. Only present if a check was performed. - `full`: The name provided matches the name held by the bank. - `close`: The name provided is a close but not exact match to the name held by the bank. - `cannot_perform_verification`: A verification was attempted but could not be completed. This can happen for a number of reasons, including the account holder's bank not participating in the verification scheme, the account not being eligible for verification (e.g. the account holder has opted out), or the bank details not being resolvable, among others. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a customer bank account `PUT /customer_bank_accounts/{customer_bank_account_id}` Updates a customer bank account object. Only the metadata parameter is allowed. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_bank_account_id` | path | string | Yes | The customer bank account id | ### Request body Wrap request body attributes in a `customer_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customer_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. The full name provided when the customer is created is stored and is available via the API, but is transliterated, upcased, and truncated to 18 characters in bank submissions. This field is required unless the request includes a [customer bank account token](#javascript-flow-customer-bank-account-tokens). | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `bank_account_token` | string \| null | No | A token to uniquely refer to a set of bank account details. This feature is still in early access and is only available for certain organisations. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `trusted_recipient` | boolean | No | Whether this customer bank account is registered as a trusted recipient for Outbound Payments. Only present when the feature is enabled for the organisation. | | `payer_name_verification_result` | enum | No | The result of the payer name verification check performed when the bank account was created. Only present if a check was performed. - `full`: The name provided matches the name held by the bank. - `close`: The name provided is a close but not exact match to the name held by the bank. - `cannot_perform_verification`: A verification was attempted but could not be completed. This can happen for a number of reasons, including the account holder's bank not participating in the verification scheme, the account not being eligible for verification (e.g. the account holder has opted out), or the bank details not being resolvable, among others. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Disable a customer bank account `POST /customer_bank_accounts/{customer_bank_account_id}/actions/disable` Immediately cancels all associated mandates and cancellable payments. This will return a `disable_failed` error if the bank account has already been disabled. A disabled bank account can be re-enabled by creating a new bank account resource with the same details. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_bank_account_id` | path | string | Yes | The customer bank account id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customer_bank_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. The full name provided when the customer is created is stored and is available via the API, but is transliterated, upcased, and truncated to 18 characters in bank submissions. This field is required unless the request includes a [customer bank account token](#javascript-flow-customer-bank-account-tokens). | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `country_code` | string \| null | No | [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements). Defaults to the country code of the `iban` if supplied, otherwise is required. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `bank_account_token` | string \| null | No | A token to uniquely refer to a set of bank account details. This feature is still in early access and is only available for certain organisations. | | `enabled` | boolean | No | Boolean value showing whether the bank account is enabled or disabled. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `trusted_recipient` | boolean | No | Whether this customer bank account is registered as a trusted recipient for Outbound Payments. Only present when the feature is enabled for the organisation. | | `payer_name_verification_result` | enum | No | The result of the payer name verification check performed when the bank account was created. Only present if a check was performed. - `full`: The name provided matches the name held by the bank. - `close`: The name provided is a close but not exact match to the name held by the bank. - `cannot_perform_verification`: A verification was attempted but could not be completed. This can happen for a number of reasons, including the account holder's bank not participating in the verification scheme, the account not being eligible for verification (e.g. the account holder has opted out), or the bank details not being resolvable, among others. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## customer-notification URL: https://docs.gocardless.com/docs/api-reference/customer-notification # Customer Notification Source: https://docs.gocardless.com/docs/api-reference/customer-notification ## Handle a notification `POST /customer_notifications/{customer_notification_id}/actions/handle` "Handling" a notification means that you have sent the notification yourself (and don't want GoCardless to send it). If the notification has already been actioned, or the deadline to notify has passed, this endpoint will return an `already_actioned` error and you should not take further action. This endpoint takes no additional parameters. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `customer_notification_id` | path | string | Yes | The customer notification id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `customer_notifications` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | The id of the notification. | | `type` | enum | No | The type of notification the customer shall receive. Note: today, only `payment_created`, `mandate_created` and `subscription_created` notifications are actually supported. The remaining values are reserved for now. Making a request for an event of any other type will get a `403` `customer_notifications_notification_type_forbidden` error. | | `action_taken` | enum | No | The action that was taken on the notification. Currently this can only be `handled`, which means the integrator sent the notification themselves. | | `action_taken_at` | string \| null | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this action was taken. | | `action_taken_by` | string \| null | No | A string identifying the integrator who was able to handle this notification. | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## event URL: https://docs.gocardless.com/docs/api-reference/event # Event Source: https://docs.gocardless.com/docs/api-reference/event ## List events `GET /events` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your events.

Important: This endpoint will no longer return events older than 18 months, including when filtering by resource. This takes effect no sooner than 1 August 2026 in sandbox environments, and no sooner than 1 October 2026 in live environments.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `billing_request` | query | string | No | ID of a [billing request](#billing-requests-billing-requests). If specified, this endpoint will return all events for the given billing request. | | `creditor` | query | string | No | ID of an [creditor](#core-endpoints-creditors). If specified, this endpoint will return all events for the given creditor. | | `export` | query | string | No | ID of an export. If specified, this endpoint will return all events for the given export. | | `instalment_schedule` | query | string | No | ID of an [instalment schedule](#core-endpoints-instalment-schedules). If specified, this endpoint will return all events for the given instalment schedule. | | `mandate` | query | string | No | ID of a [mandate](#core-endpoints-mandates). If specified, this endpoint will return all events for the given mandate. | | `outbound_payment` | query | string | No | ID of an [outbound_payment](#core-endpoints-outbound-payments). If specified, this endpoint will return all events for the given payment. | | `payer_authorisation` | query | string | No | ID of a [payer authorisation](#core-endpoints-payer-authorisations). | | `payment` | query | string | No | ID of a [payment](#core-endpoints-payments). If specified, this endpoint will return all events for the given payment. | | `payment_account_transaction` | query | string | No | ID of a payment account transaction. If specified, this endpoint will return all events for the given transaction. | | `payout` | query | string | No | ID of a [payout](#core-endpoints-payouts). If specified, this endpoint will return all events for the given payout. | | `refund` | query | string | No | ID of a [refund](#core-endpoints-refunds). If specified, this endpoint will return all events for the given refund. | | `subscription` | query | string | No | ID of a [subscription](#core-endpoints-subscriptions). If specified, this endpoint will return all events for the given subscription. | | `scheme_identifier` | query | string | No | ID of a [scheme identifier](#core-endpoints-scheme-identifiers). If specified, this endpoint will return all events for the given scheme identifier. | | `parent_event` | query | string | No | ID of an event. If specified, this endpoint will return all events whose parent_event is the given event ID. | | `action` | query | string | No | Limit to events with a given `action`. | | `resource_type` | query | | No | | | `include` | query | | No | Includes linked resources in the response. Must be used with the `resource_type` parameter specified. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `events` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "EV". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `resource_type` | enum | No | The resource type for this event. | | `action` | string | No | What has happened to the resource. See [Event Types](#event-types) for the possible actions. | | `customer_notifications` | array \| null | No | Present only in webhooks when an integrator is authorised to send their own notifications. See [here](/getting-started/api/handling-customer-notifications/) for further information. | | `details` | object | No | | | `metadata` | object | No | The metadata that was passed when making the API request that triggered the event (for instance, cancelling a mandate). This field will only be populated if the `details[origin]` field is `api` otherwise it will be an empty object. | | `resource_metadata` | object | No | The metadata of the resource that the event is for. For example, this field will have the same value of the `mandate[metadata]` field on the response you would receive from performing a GET request on a mandate. | | `source` | object | No | Audit information about the source of the event. | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single event `GET /events/{event_id}` Retrieves the details of a single event. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `event_id` | path | string | Yes | The event id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `events` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "EV". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `resource_type` | enum | No | The resource type for this event. | | `action` | string | No | What has happened to the resource. See [Event Types](#event-types) for the possible actions. | | `customer_notifications` | array \| null | No | Present only in webhooks when an integrator is authorised to send their own notifications. See [here](/getting-started/api/handling-customer-notifications/) for further information. | | `details` | object | No | | | `metadata` | object | No | The metadata that was passed when making the API request that triggered the event (for instance, cancelling a mandate). This field will only be populated if the `details[origin]` field is `api` otherwise it will be an empty object. | | `resource_metadata` | object | No | The metadata of the resource that the event is for. For example, this field will have the same value of the `mandate[metadata]` field on the response you would receive from performing a GET request on a mandate. | | `source` | object | No | Audit information about the source of the event. | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## export URL: https://docs.gocardless.com/docs/api-reference/export # Export Source: https://docs.gocardless.com/docs/api-reference/export ## Get a single export `GET /exports/{export_id}` Returns a single export.

Restricted: This endpoint is restricted to GoCardless Embed customers. Please [contact us](https://forms.gocardless.com/l/305971/2023-01-25/535t8n){:target="_blank"} if you are interested in using this product.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `export_id` | path | string | Yes | The export id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `exports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "EX". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `export_type` | enum | No | The type of the export | | `download_url` | string \| null | No | Download url for the export file. Subject to expiry. | | `currency` | string | No | The currency of the export (if applicable) | | `error_message` | string \| null | No | Error message if the export encountered an error during processing. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List exports `GET /exports` Returns a list of exports which are available for download.

Restricted: This endpoint is restricted to GoCardless Embed customers. Please [contact us](https://forms.gocardless.com/l/305971/2023-01-25/535t8n){:target="_blank"} if you are interested in using this product.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `exports` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "EX". | | `export_type` | enum | No | The type of the export | | `currency` | string | No | The currency of the export (if applicable) | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## funds-availability URL: https://docs.gocardless.com/docs/api-reference/funds-availability # Funds Availability Source: https://docs.gocardless.com/docs/api-reference/funds-availability ## Funds availability `GET /funds_availability/{mandate_id}` Checks if the payer's current balance is sufficient to cover the amount the merchant wants to charge within the consent parameters defined on the mandate.

Warning: Funds availability check is available for VRP mandates only.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_id` | path | string | Yes | The mandate id | | `amount` | query | string | No | The amount of the payment | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## instalment-schedule URL: https://docs.gocardless.com/docs/api-reference/instalment-schedule # Instalment Schedule Source: https://docs.gocardless.com/docs/api-reference/instalment-schedule ## Create (with dates) `POST /instalment_schedules/create_with_dates` Creates a new instalment schedule object, along with the associated payments. This API is recommended if you know the specific dates you wish to charge. Otherwise, please check out the [scheduling version](#instalment-schedules-create-with-schedule). The `instalments` property is an array of payment properties (`amount` and `charge_date`). It can take quite a while to create the associated payments, so the API will return the status as `pending` initially. When processing has completed, a subsequent GET request for the instalment schedule will either have the status `success` and link to the created payments, or the status `error` and detailed information about the failures. ### Request body Wrap request body attributes in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `total_amount` | string / integer | Yes | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `app_fee` | string / integer | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `payment_reference` | string \| null | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `instalments` | array | Yes | An explicit array of instalment payments, each specifying at least an `amount` and `charge_date`. See [create (with dates)](#instalment-schedules-create-with-dates) | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "IS". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `total_amount` | integer | No | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `name` | string | No | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending`: we're waiting for GC to create the payments - `active`: the payments have been created, and the schedule is active - `creation_failed`: payment creation failed - `completed`: we have passed the date of the final payment and all payments have been collected - `cancelled`: the schedule has been cancelled - `errored`: one or more payments have failed | | `payment_errors` | object | No | If the status is `creation_failed`, this property will be populated with validation failures from the individual payments, arranged by the index of the payment that failed. | | `links` | object | No | Links to associated objects | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Create (with schedule) `POST /instalment_schedules/create_with_schedule` Creates a new instalment schedule object, along with the associated payments. This API is recommended if you wish to use the GoCardless scheduling logic. For finer control over the individual dates, please check out the [alternative version](#instalment-schedules-create-with-dates). It can take quite a while to create the associated payments, so the API will return the status as `pending` initially. When processing has completed, a subsequent GET request for the instalment schedule will either have the status `success` and link to the created payments, or the status `error` and detailed information about the failures. ### Request body Wrap request body attributes in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `total_amount` | string / integer | Yes | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `app_fee` | string / integer | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `payment_reference` | string \| null | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `instalments` | object | Yes | Frequency of the payments you want to create, together with an array of payment amounts to be collected, with a specified start date for the first payment. See [create (with schedule)](#instalment-schedules-create-with-schedule) | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "IS". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `total_amount` | integer | No | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `name` | string | No | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending`: we're waiting for GC to create the payments - `active`: the payments have been created, and the schedule is active - `creation_failed`: payment creation failed - `completed`: we have passed the date of the final payment and all payments have been collected - `cancelled`: the schedule has been cancelled - `errored`: one or more payments have failed | | `payment_errors` | object | No | If the status is `creation_failed`, this property will be populated with validation failures from the individual payments, arranged by the index of the payment that failed. | | `links` | object | No | Links to associated objects | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List instalment schedules `GET /instalment_schedules` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your instalment schedules. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `status` | query | | No | At most five valid status values | | `mandate` | query | string | No | ID of the associated [mandate](#core-endpoints-mandates) which the instalment schedule will create payments against. | | `customer` | query | string | No | ID of the associated [customer](#core-endpoints-customers). | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `instalment_schedules` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "IS". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `total_amount` | integer | No | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `name` | string | No | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending`: we're waiting for GC to create the payments - `active`: the payments have been created, and the schedule is active - `creation_failed`: payment creation failed - `completed`: we have passed the date of the final payment and all payments have been collected - `cancelled`: the schedule has been cancelled - `errored`: one or more payments have failed | | `payment_errors` | object | No | If the status is `creation_failed`, this property will be populated with validation failures from the individual payments, arranged by the index of the payment that failed. | | `links` | object | No | Links to associated objects | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single instalment schedule `GET /instalment_schedules/{instalment_schedule_id}` Retrieves the details of an existing instalment schedule. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `instalment_schedule_id` | path | string | Yes | The instalment schedule id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "IS". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `total_amount` | integer | No | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `name` | string | No | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending`: we're waiting for GC to create the payments - `active`: the payments have been created, and the schedule is active - `creation_failed`: payment creation failed - `completed`: we have passed the date of the final payment and all payments have been collected - `cancelled`: the schedule has been cancelled - `errored`: one or more payments have failed | | `payment_errors` | object | No | If the status is `creation_failed`, this property will be populated with validation failures from the individual payments, arranged by the index of the payment that failed. | | `links` | object | No | Links to associated objects | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update an instalment schedule `PUT /instalment_schedules/{instalment_schedule_id}` Updates an instalment schedule. This accepts only the metadata parameter. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `instalment_schedule_id` | path | string | Yes | The instalment schedule id | ### Request body Wrap request body attributes in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "IS". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `total_amount` | integer | No | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `name` | string | No | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending`: we're waiting for GC to create the payments - `active`: the payments have been created, and the schedule is active - `creation_failed`: payment creation failed - `completed`: we have passed the date of the final payment and all payments have been collected - `cancelled`: the schedule has been cancelled - `errored`: one or more payments have failed | | `payment_errors` | object | No | If the status is `creation_failed`, this property will be populated with validation failures from the individual payments, arranged by the index of the payment that failed. | | `links` | object | No | Links to associated objects | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Cancel an instalment schedule `POST /instalment_schedules/{instalment_schedule_id}/actions/cancel` Immediately cancels an instalment schedule; no further payments will be collected for it. This will fail with a `cancellation_failed` error if the instalment schedule is already cancelled or has completed. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `instalment_schedule_id` | path | string | Yes | The instalment schedule id | ### Request body Wrap request body attributes in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `instalment_schedules` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "IS". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `total_amount` | integer | No | The total amount of the instalment schedule, defined as the sum of all individual payments, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). If the requested payment amounts do not sum up correctly, a validation error will be returned. | | `name` | string | No | Name of the instalment schedule, up to 100 chars. This name will also be copied to the payments of the instalment schedule if you use schedule-based creation. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending`: we're waiting for GC to create the payments - `active`: the payments have been created, and the schedule is active - `creation_failed`: payment creation failed - `completed`: we have passed the date of the final payment and all payments have been collected - `cancelled`: the schedule has been cancelled - `errored`: one or more payments have failed | | `payment_errors` | object | No | If the status is `creation_failed`, this property will be populated with validation failures from the individual payments, arranged by the index of the payment that failed. | | `links` | object | No | Links to associated objects | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## institution URL: https://docs.gocardless.com/docs/api-reference/institution # Institution Source: https://docs.gocardless.com/docs/api-reference/institution ## List Institutions `GET /institutions` Returns a list of supported institutions. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `country_code` | query | string | No | [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code. The country code of the institution. If nothing is provided, institutions with the country code 'GB' are returned by default. | | `scheme` | query | string | No | The scheme that institutions support. The available options include `faster_payments`, `sepa_credit_transfer`, and `sepa_instant_credit_transfer`. If nothing is provided, no scheme filter is applied to the returned institutions. | | `feature` | query | string | No | The feature that institutions support. The available options include `pis`, `vrp_sweeping`, and `vrp_commercial`. If nothing is provided, institutions supporting 'pis' are returned by default. | | `branch_code` | query | string | No | (Currently only supports UK sort-codes) The six-digit number that identifies both the bank and the specific branch where an account is held, eg. '601234'. | | `include_disabled` | query | enum | No | Indicates whether to include temporarily disabled institutions in the response. If not provided or set to false, only enabled institutions will be returned. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `institutions` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | The unique identifier for this institution | | `name` | string | No | A human readable name for this institution | | `icon_url` | string | No | A URL pointing to the icon for this institution | | `logo_url` | string | No | A URL pointing to the logo for this institution | | `roles` | array | No | The roles assigned to this institution, representing the open banking features it supports. | | `country_code` | string | No | [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code. The country code of the institution. If nothing is provided, institutions with the country code 'GB' are returned by default. | | `limits` | object \| null | No | Defines individual limits for business and personal accounts. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List institutions for Billing Request `GET /billing_requests/{billing_request_id}/institutions` Returns all institutions valid for a Billing Request. This endpoint is currently supported only for FasterPayments.

Restricted: this endpoint is restricted to [GoCardless Pro](https://gocardless.com/pricing) and [GoCardless Enterprise](https://gocardless.com/pricing) accounts with the [custom payment pages upgrade](https://hub.gocardless.com/s/article/Custom-payment-pages).

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `billing_request_id` | path | string | Yes | The billing request id | | `search` | query | string | No | A search substring for retrieving institution(s), based on the institution's name. | | `ids` | query | | No | ID(s) of the institution(s) to retrieve. More than one ID can be specified using a comma-separated string. | | `country_code` | query | string | Yes | [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code. The country code of the institution. If nothing is provided, institutions with the country code 'GB' are returned by default. | | `include_disabled` | query | enum | No | Indicates whether to include temporarily disabled institutions in the response. If not provided or set to false, only enabled institutions will be returned. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `institutions` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | The unique identifier for this institution | | `name` | string | No | A human readable name for this institution | | `icon_url` | string | No | A URL pointing to the icon for this institution | | `logo_url` | string | No | A URL pointing to the logo for this institution | | `country_code` | string | No | [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code. The country code of the institution. If nothing is provided, institutions with the country code 'GB' are returned by default. | | `autocompletes_collect_bank_account` | boolean | No | Flag to show if selecting this institution in the select_institution action can auto-complete the collect_bank_account action. The bank can return the payer's bank account details to GoCardless. | | `status` | enum | No | The status of the institution | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## logo URL: https://docs.gocardless.com/docs/api-reference/logo # Logo Source: https://docs.gocardless.com/docs/api-reference/logo ## Create a logo associated with a creditor `POST /branding/logos` Creates a new logo associated with a creditor. If a creditor already has a logo, this will update the existing logo linked to the creditor. We support JPG and PNG formats. Your logo will be scaled to a maximum of 300px by 40px. For more guidance on how to upload logos that will look great across your customer payment page and notification emails see [here](https://developer.gocardless.com/gc-embed/setting-up-branding#tips_for_uploading_your_logo).

Restricted: This endpoint is restricted to GoCardless Embed customers. Please [contact us](https://forms.gocardless.com/l/305971/2023-01-25/535t8n){:target="_blank"} if you are interested in using this product.

### Request body Wrap request body attributes in a `logos` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `image` | string | Yes | Base64 encoded string. | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `logos` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "LO". | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## mandate URL: https://docs.gocardless.com/docs/api-reference/mandate # Mandate Source: https://docs.gocardless.com/docs/api-reference/mandate ## Create a mandate `POST /mandates` Creates a new mandate object.

Restricted: this endpoint requires approved [custom payment pages](https://support.gocardless.com/hc/en-gb/articles/115004521925-Custom-Payment-Pages).

Note: this endpoint is a legacy API endpoint and does not support GoCardless' newest features. We recommend using the [Billing Requests API](/billing-requests/overview) instead.

Warning: by default, the ability to provide a custom mandate reference is switched off. The banking system rules for valid references are quite complex, and we recommend allowing GoCardless to generate it. If you would like to provide custom references, please contact support.

### Request body Wrap request body attributes in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `reference` | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | | `scheme` | string \| null | No | Bank payment scheme to which this mandate and associated payments are submitted. Can be supplied or automatically detected from the customer's bank account. | | `payer_ip_address` | string \| null | No | For ACH customers only. Required for ACH customers. A string containing the IP address of the payer to whom the mandate belongs (i.e. as a result of their completion of a mandate setup flow in their browser). Not required for creating offline mandates where `authorisation_source` is set to telephone or paper. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `authorisation_source` | enum | No | This field is ACH specific, sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This is the way that the payer gives authorisation to the merchant. web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC code: WEB) telephone: Authorisation is provided orally over telephone (maps to SEC code: TEL) paper: Authorisation is provided in writing and signed, or similarly authenticated (maps to SEC code: PPD) | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `reference` | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | | `status` | enum | No | One of: - `pending_customer_approval`: the mandate has not yet been signed by the second customer - `pending_submission`: the mandate has not yet been submitted to the customer's bank - `submitted`: the mandate has been submitted to the customer's bank but has not been processed yet - `active`: the mandate has been successfully set up by the customer's bank - `suspended_by_payer`: the mandate has been suspended by payer - `failed`: the mandate could not be created - `cancelled`: the mandate has been cancelled - `expired`: the mandate has expired due to dormancy - `consumed`: the mandate has been consumed and cannot be reused (note that this only applies to schemes that are per-payment authorised) - `blocked`: the mandate has been blocked and payments cannot be created | | `scheme` | string \| null | No | Bank payment scheme to which this mandate and associated payments are submitted. Can be supplied or automatically detected from the customer's bank account. | | `mandate_type` | enum \| null | No | Mandate type | | `next_possible_charge_date` | string \| null | No | The earliest date that can be used as a `charge_date` on any newly created payment for this mandate. This value will change over time. | | `next_possible_standard_ach_charge_date` | string \| null | No | If this is an ACH mandate, the earliest date that can be used as a `charge_date` on any newly created payment to be charged through standard ACH, rather than Faster ACH. This value will change over time. It is only present in the API response for ACH mandates. | | `payments_require_approval` | boolean | No | Boolean value showing whether payments and subscriptions under this mandate require approval via an automated email before being processed. | | `verified_at` | string \| null | No | [Timestamp](#api-usage-dates-and-times) recording when this mandate was verified. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `consent_parameters` | object \| null | No | (Optional) Payto and VRP Scheme specific information | | `authorisation_source` | enum | No | This field is ACH specific, sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This is the way that the payer gives authorisation to the merchant. web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC code: WEB) telephone: Authorisation is provided orally over telephone (maps to SEC code: TEL) paper: Authorisation is provided in writing and signed, or similarly authenticated (maps to SEC code: PPD) | | `funds_settlement` | enum | No | This field will decide how GoCardless handles settlement of funds from the customer. - `managed` will be moved through GoCardless' account, batched, and payed out. - `direct` will be a direct transfer from the payer's account to the merchant where invoicing will be handled separately. | | `consent_type` | enum \| null | No | (Optional) Specifies the type of authorisation agreed between the payer and merchant. It can be set to one-off, recurring or standing for ACH, or single, recurring and sporadic for PAD. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List mandates `GET /mandates` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your mandates. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `customer` | query | string | No | ID of a [customer](#core-endpoints-customers). If specified, this endpoint will return all mandates for the given customer. Cannot be used in conjunction with `customer_bank_account` or `creditor` | | `creditor` | query | string | No | ID of a [creditor](#core-endpoints-creditors). If specified, this endpoint will return all mandates for the given creditor. Cannot be used in conjunction with `customer` or `customer_bank_account` | | `customer_bank_account` | query | string | No | ID of a [customer bank account](#core-endpoints-customer-bank-accounts). If specified, this endpoint will return all mandates for the given bank account. Cannot be used in conjunction with `customer` or `creditor` | | `status` | query | | No | One or more valid statuses | | `scheme` | query | | No | Scheme you'd like to retrieve mandates for | | `mandate_type` | query | enum \| null | No | Mandate type | | `reference` | query | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `mandates` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `reference` | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | | `status` | enum | No | One of: - `pending_customer_approval`: the mandate has not yet been signed by the second customer - `pending_submission`: the mandate has not yet been submitted to the customer's bank - `submitted`: the mandate has been submitted to the customer's bank but has not been processed yet - `active`: the mandate has been successfully set up by the customer's bank - `suspended_by_payer`: the mandate has been suspended by payer - `failed`: the mandate could not be created - `cancelled`: the mandate has been cancelled - `expired`: the mandate has expired due to dormancy - `consumed`: the mandate has been consumed and cannot be reused (note that this only applies to schemes that are per-payment authorised) - `blocked`: the mandate has been blocked and payments cannot be created | | `scheme` | string \| null | No | Bank payment scheme to which this mandate and associated payments are submitted. Can be supplied or automatically detected from the customer's bank account. | | `mandate_type` | enum \| null | No | Mandate type | | `next_possible_charge_date` | string \| null | No | The earliest date that can be used as a `charge_date` on any newly created payment for this mandate. This value will change over time. | | `next_possible_standard_ach_charge_date` | string \| null | No | If this is an ACH mandate, the earliest date that can be used as a `charge_date` on any newly created payment to be charged through standard ACH, rather than Faster ACH. This value will change over time. It is only present in the API response for ACH mandates. | | `payments_require_approval` | boolean | No | Boolean value showing whether payments and subscriptions under this mandate require approval via an automated email before being processed. | | `verified_at` | string \| null | No | [Timestamp](#api-usage-dates-and-times) recording when this mandate was verified. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `consent_parameters` | object \| null | No | (Optional) Payto and VRP Scheme specific information | | `authorisation_source` | enum | No | This field is ACH specific, sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This is the way that the payer gives authorisation to the merchant. web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC code: WEB) telephone: Authorisation is provided orally over telephone (maps to SEC code: TEL) paper: Authorisation is provided in writing and signed, or similarly authenticated (maps to SEC code: PPD) | | `funds_settlement` | enum | No | This field will decide how GoCardless handles settlement of funds from the customer. - `managed` will be moved through GoCardless' account, batched, and payed out. - `direct` will be a direct transfer from the payer's account to the merchant where invoicing will be handled separately. | | `consent_type` | enum \| null | No | (Optional) Specifies the type of authorisation agreed between the payer and merchant. It can be set to one-off, recurring or standing for ACH, or single, recurring and sporadic for PAD. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single mandate `GET /mandates/{mandate_id}` Retrieves the details of an existing mandate. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_id` | path | string | Yes | The mandate id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `reference` | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | | `status` | enum | No | One of: - `pending_customer_approval`: the mandate has not yet been signed by the second customer - `pending_submission`: the mandate has not yet been submitted to the customer's bank - `submitted`: the mandate has been submitted to the customer's bank but has not been processed yet - `active`: the mandate has been successfully set up by the customer's bank - `suspended_by_payer`: the mandate has been suspended by payer - `failed`: the mandate could not be created - `cancelled`: the mandate has been cancelled - `expired`: the mandate has expired due to dormancy - `consumed`: the mandate has been consumed and cannot be reused (note that this only applies to schemes that are per-payment authorised) - `blocked`: the mandate has been blocked and payments cannot be created | | `scheme` | string \| null | No | Bank payment scheme to which this mandate and associated payments are submitted. Can be supplied or automatically detected from the customer's bank account. | | `mandate_type` | enum \| null | No | Mandate type | | `next_possible_charge_date` | string \| null | No | The earliest date that can be used as a `charge_date` on any newly created payment for this mandate. This value will change over time. | | `next_possible_standard_ach_charge_date` | string \| null | No | If this is an ACH mandate, the earliest date that can be used as a `charge_date` on any newly created payment to be charged through standard ACH, rather than Faster ACH. This value will change over time. It is only present in the API response for ACH mandates. | | `payments_require_approval` | boolean | No | Boolean value showing whether payments and subscriptions under this mandate require approval via an automated email before being processed. | | `verified_at` | string \| null | No | [Timestamp](#api-usage-dates-and-times) recording when this mandate was verified. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `consent_parameters` | object \| null | No | (Optional) Payto and VRP Scheme specific information | | `authorisation_source` | enum | No | This field is ACH specific, sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This is the way that the payer gives authorisation to the merchant. web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC code: WEB) telephone: Authorisation is provided orally over telephone (maps to SEC code: TEL) paper: Authorisation is provided in writing and signed, or similarly authenticated (maps to SEC code: PPD) | | `funds_settlement` | enum | No | This field will decide how GoCardless handles settlement of funds from the customer. - `managed` will be moved through GoCardless' account, batched, and payed out. - `direct` will be a direct transfer from the payer's account to the merchant where invoicing will be handled separately. | | `consent_type` | enum \| null | No | (Optional) Specifies the type of authorisation agreed between the payer and merchant. It can be set to one-off, recurring or standing for ACH, or single, recurring and sporadic for PAD. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a mandate `PUT /mandates/{mandate_id}` Updates a mandate object. This accepts only the metadata parameter. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_id` | path | string | Yes | The mandate id | ### Request body Wrap request body attributes in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `reference` | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | | `status` | enum | No | One of: - `pending_customer_approval`: the mandate has not yet been signed by the second customer - `pending_submission`: the mandate has not yet been submitted to the customer's bank - `submitted`: the mandate has been submitted to the customer's bank but has not been processed yet - `active`: the mandate has been successfully set up by the customer's bank - `suspended_by_payer`: the mandate has been suspended by payer - `failed`: the mandate could not be created - `cancelled`: the mandate has been cancelled - `expired`: the mandate has expired due to dormancy - `consumed`: the mandate has been consumed and cannot be reused (note that this only applies to schemes that are per-payment authorised) - `blocked`: the mandate has been blocked and payments cannot be created | | `scheme` | string \| null | No | Bank payment scheme to which this mandate and associated payments are submitted. Can be supplied or automatically detected from the customer's bank account. | | `mandate_type` | enum \| null | No | Mandate type | | `next_possible_charge_date` | string \| null | No | The earliest date that can be used as a `charge_date` on any newly created payment for this mandate. This value will change over time. | | `next_possible_standard_ach_charge_date` | string \| null | No | If this is an ACH mandate, the earliest date that can be used as a `charge_date` on any newly created payment to be charged through standard ACH, rather than Faster ACH. This value will change over time. It is only present in the API response for ACH mandates. | | `payments_require_approval` | boolean | No | Boolean value showing whether payments and subscriptions under this mandate require approval via an automated email before being processed. | | `verified_at` | string \| null | No | [Timestamp](#api-usage-dates-and-times) recording when this mandate was verified. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `consent_parameters` | object \| null | No | (Optional) Payto and VRP Scheme specific information | | `authorisation_source` | enum | No | This field is ACH specific, sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This is the way that the payer gives authorisation to the merchant. web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC code: WEB) telephone: Authorisation is provided orally over telephone (maps to SEC code: TEL) paper: Authorisation is provided in writing and signed, or similarly authenticated (maps to SEC code: PPD) | | `funds_settlement` | enum | No | This field will decide how GoCardless handles settlement of funds from the customer. - `managed` will be moved through GoCardless' account, batched, and payed out. - `direct` will be a direct transfer from the payer's account to the merchant where invoicing will be handled separately. | | `consent_type` | enum \| null | No | (Optional) Specifies the type of authorisation agreed between the payer and merchant. It can be set to one-off, recurring or standing for ACH, or single, recurring and sporadic for PAD. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Cancel a mandate `POST /mandates/{mandate_id}/actions/cancel` Immediately cancels a mandate and all associated cancellable payments. Any metadata supplied to this endpoint will be stored on the mandate cancellation event it causes. This will fail with a `cancellation_failed` error if the mandate is already cancelled. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_id` | path | string | Yes | The mandate id | ### Request body Wrap request body attributes in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `reference` | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | | `status` | enum | No | One of: - `pending_customer_approval`: the mandate has not yet been signed by the second customer - `pending_submission`: the mandate has not yet been submitted to the customer's bank - `submitted`: the mandate has been submitted to the customer's bank but has not been processed yet - `active`: the mandate has been successfully set up by the customer's bank - `suspended_by_payer`: the mandate has been suspended by payer - `failed`: the mandate could not be created - `cancelled`: the mandate has been cancelled - `expired`: the mandate has expired due to dormancy - `consumed`: the mandate has been consumed and cannot be reused (note that this only applies to schemes that are per-payment authorised) - `blocked`: the mandate has been blocked and payments cannot be created | | `scheme` | string \| null | No | Bank payment scheme to which this mandate and associated payments are submitted. Can be supplied or automatically detected from the customer's bank account. | | `mandate_type` | enum \| null | No | Mandate type | | `next_possible_charge_date` | string \| null | No | The earliest date that can be used as a `charge_date` on any newly created payment for this mandate. This value will change over time. | | `next_possible_standard_ach_charge_date` | string \| null | No | If this is an ACH mandate, the earliest date that can be used as a `charge_date` on any newly created payment to be charged through standard ACH, rather than Faster ACH. This value will change over time. It is only present in the API response for ACH mandates. | | `payments_require_approval` | boolean | No | Boolean value showing whether payments and subscriptions under this mandate require approval via an automated email before being processed. | | `verified_at` | string \| null | No | [Timestamp](#api-usage-dates-and-times) recording when this mandate was verified. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `consent_parameters` | object \| null | No | (Optional) Payto and VRP Scheme specific information | | `authorisation_source` | enum | No | This field is ACH specific, sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This is the way that the payer gives authorisation to the merchant. web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC code: WEB) telephone: Authorisation is provided orally over telephone (maps to SEC code: TEL) paper: Authorisation is provided in writing and signed, or similarly authenticated (maps to SEC code: PPD) | | `funds_settlement` | enum | No | This field will decide how GoCardless handles settlement of funds from the customer. - `managed` will be moved through GoCardless' account, batched, and payed out. - `direct` will be a direct transfer from the payer's account to the merchant where invoicing will be handled separately. | | `consent_type` | enum \| null | No | (Optional) Specifies the type of authorisation agreed between the payer and merchant. It can be set to one-off, recurring or standing for ACH, or single, recurring and sporadic for PAD. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Reinstate a mandate `POST /mandates/{mandate_id}/actions/reinstate` Reinstates a cancelled or expired mandate to the banks. You will receive a `resubmission_requested` webhook, but after that reinstating the mandate follows the same process as its initial creation, so you will receive a `submitted` webhook, followed by a `reinstated` or `failed` webhook up to two working days later. Any metadata supplied to this endpoint will be stored on the `resubmission_requested` event it causes. This will fail with a `mandate_not_inactive` error if the mandate is already being submitted, or is active. Mandates can be resubmitted up to 10 times.

Restricted: this endpoint requires approved [custom payment pages](https://support.gocardless.com/hc/en-gb/articles/115004521925-Custom-Payment-Pages). To instead use the GoCardless hosted payment pages, see the [redirect flows](#core-endpoints-redirect-flows) endpoint.

Warning: A mandate can only be reinstated if it has been cancelled through the dashboard or the API. Any mandate that has been cancelled by the bank cannot be reinstated.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_id` | path | string | Yes | The mandate id | ### Request body Wrap request body attributes in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `reference` | string \| null | No | Unique reference. Different schemes have different length and [character set](#appendix-character-sets) requirements. GoCardless will generate a unique reference satisfying the different scheme requirements if this field is left blank. | | `status` | enum | No | One of: - `pending_customer_approval`: the mandate has not yet been signed by the second customer - `pending_submission`: the mandate has not yet been submitted to the customer's bank - `submitted`: the mandate has been submitted to the customer's bank but has not been processed yet - `active`: the mandate has been successfully set up by the customer's bank - `suspended_by_payer`: the mandate has been suspended by payer - `failed`: the mandate could not be created - `cancelled`: the mandate has been cancelled - `expired`: the mandate has expired due to dormancy - `consumed`: the mandate has been consumed and cannot be reused (note that this only applies to schemes that are per-payment authorised) - `blocked`: the mandate has been blocked and payments cannot be created | | `scheme` | string \| null | No | Bank payment scheme to which this mandate and associated payments are submitted. Can be supplied or automatically detected from the customer's bank account. | | `mandate_type` | enum \| null | No | Mandate type | | `next_possible_charge_date` | string \| null | No | The earliest date that can be used as a `charge_date` on any newly created payment for this mandate. This value will change over time. | | `next_possible_standard_ach_charge_date` | string \| null | No | If this is an ACH mandate, the earliest date that can be used as a `charge_date` on any newly created payment to be charged through standard ACH, rather than Faster ACH. This value will change over time. It is only present in the API response for ACH mandates. | | `payments_require_approval` | boolean | No | Boolean value showing whether payments and subscriptions under this mandate require approval via an automated email before being processed. | | `verified_at` | string \| null | No | [Timestamp](#api-usage-dates-and-times) recording when this mandate was verified. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | No | | | `consent_parameters` | object \| null | No | (Optional) Payto and VRP Scheme specific information | | `authorisation_source` | enum | No | This field is ACH specific, sometimes referred to as [SEC code](https://www.moderntreasury.com/learn/sec-codes). This is the way that the payer gives authorisation to the merchant. web: Authorisation is Internet Initiated or via Mobile Entry (maps to SEC code: WEB) telephone: Authorisation is provided orally over telephone (maps to SEC code: TEL) paper: Authorisation is provided in writing and signed, or similarly authenticated (maps to SEC code: PPD) | | `funds_settlement` | enum | No | This field will decide how GoCardless handles settlement of funds from the customer. - `managed` will be moved through GoCardless' account, batched, and payed out. - `direct` will be a direct transfer from the payer's account to the merchant where invoicing will be handled separately. | | `consent_type` | enum \| null | No | (Optional) Specifies the type of authorisation agreed between the payer and merchant. It can be set to one-off, recurring or standing for ACH, or single, recurring and sporadic for PAD. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## mandate-import URL: https://docs.gocardless.com/docs/api-reference/mandate-import # Mandate Import Source: https://docs.gocardless.com/docs/api-reference/mandate-import ## Create a new mandate import `POST /mandate_imports` Mandate imports are first created, before mandates are added one-at-a-time, so this endpoint merely signals the start of the import process. Once you've finished adding entries to an import, you should [submit](#mandate-imports-submit-a-mandate-import) it. ### Request body Wrap request body attributes in a `mandate_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `scheme` | enum | Yes | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to" and "sepa_core" are supported. | | `links` | object | No | Related resources | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandate_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "IM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | Yes | The status of the mandate import. - `created`: A new mandate import. - `submitted`: After the integrator has finished adding mandates and [submitted](#mandate-imports-submit-a-mandate-import) the import. - `cancelled`: If the integrator [cancelled](#mandate-imports-cancel-a-mandate-import) the mandate import. - `processing`: Once a mandate import has been approved by a GoCardless team member it will be in this state while mandates are imported. - `processed`: When all mandates have been imported successfully. | | `scheme` | enum | Yes | The scheme of the mandates to be imported.
All mandates in a single mandate import must be for the same scheme. | | `links` | object | Yes | Related resources | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a mandate import `GET /mandate_imports/{mandate_import_id}` Returns a single mandate import. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_import_id` | path | string | Yes | The mandate import id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandate_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "IM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | Yes | The status of the mandate import. - `created`: A new mandate import. - `submitted`: After the integrator has finished adding mandates and [submitted](#mandate-imports-submit-a-mandate-import) the import. - `cancelled`: If the integrator [cancelled](#mandate-imports-cancel-a-mandate-import) the mandate import. - `processing`: Once a mandate import has been approved by a GoCardless team member it will be in this state while mandates are imported. - `processed`: When all mandates have been imported successfully. | | `scheme` | enum | Yes | The scheme of the mandates to be imported.
All mandates in a single mandate import must be for the same scheme. | | `links` | object | Yes | Related resources | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Submit a mandate import `POST /mandate_imports/{mandate_import_id}/actions/submit` Submits the mandate import, which allows it to be processed by a member of the GoCardless team. Once the import has been submitted, it can no longer have entries added to it. In our sandbox environment, to aid development, we automatically process mandate imports approximately 10 seconds after they are submitted. This will allow you to test both the "submitted" response and wait for the webhook to confirm the processing has begun. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_import_id` | path | string | Yes | The mandate import id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandate_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "IM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | Yes | The status of the mandate import. - `created`: A new mandate import. - `submitted`: After the integrator has finished adding mandates and [submitted](#mandate-imports-submit-a-mandate-import) the import. - `cancelled`: If the integrator [cancelled](#mandate-imports-cancel-a-mandate-import) the mandate import. - `processing`: Once a mandate import has been approved by a GoCardless team member it will be in this state while mandates are imported. - `processed`: When all mandates have been imported successfully. | | `scheme` | enum | Yes | The scheme of the mandates to be imported.
All mandates in a single mandate import must be for the same scheme. | | `links` | object | Yes | Related resources | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Cancel a mandate import `POST /mandate_imports/{mandate_import_id}/actions/cancel` Cancels the mandate import, which aborts the import process and stops the mandates being set up in GoCardless. Once the import has been cancelled, it can no longer have entries added to it. Mandate imports which have already been submitted or processed cannot be cancelled. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_import_id` | path | string | Yes | The mandate import id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandate_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "IM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | Yes | The status of the mandate import. - `created`: A new mandate import. - `submitted`: After the integrator has finished adding mandates and [submitted](#mandate-imports-submit-a-mandate-import) the import. - `cancelled`: If the integrator [cancelled](#mandate-imports-cancel-a-mandate-import) the mandate import. - `processing`: Once a mandate import has been approved by a GoCardless team member it will be in this state while mandates are imported. - `processed`: When all mandates have been imported successfully. | | `scheme` | enum | Yes | The scheme of the mandates to be imported.
All mandates in a single mandate import must be for the same scheme. | | `links` | object | Yes | Related resources | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## mandate-import-entry URL: https://docs.gocardless.com/docs/api-reference/mandate-import-entry # Mandate Import Entry Source: https://docs.gocardless.com/docs/api-reference/mandate-import-entry ## Add a mandate import entry `POST /mandate_import_entries` For an existing [mandate import](#core-endpoints-mandate-imports), this endpoint can be used to add individual mandates to be imported into GoCardless. You can add no more than 30,000 rows to a single mandate import. If you attempt to go over this limit, the API will return a `record_limit_exceeded` error. ### Request body Wrap request body attributes in a `mandate_import_entries` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `links` | object | Yes | | | `record_identifier` | string \| null | No | A unique identifier for this entry, which you can use (once the import has been processed by GoCardless) to identify the records that have been created. Limited to 255 characters. | | `mandate` | object | No | | | `customer` | object | Yes | | | `bank_account` | object | Yes | | | `amendment` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandate_import_entries` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `record_identifier` | string \| null | Yes | A unique identifier for this entry, which you can use (once the import has been processed by GoCardless) to identify the records that have been created. Limited to 255 characters. | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `links` | object | Yes | Related resources | | `processing_errors` | object \| null | Yes | Per-resource processing errors | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List all mandate import entries `GET /mandate_import_entries` For an existing mandate import, this endpoint lists all of the entries attached. After a mandate import has been submitted, you can use this endpoint to associate records in your system (using the `record_identifier` that you provided when creating the mandate import). ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `mandate_import` | query | string | Yes | Unique identifier, beginning with "IM". | | `status` | query | enum | No | One of: - `successfully_processed`: the entry has been imported and the associated records created. - `unsuccessfully_processed`: the entry could not be processed due to an error, see the 'processing_errors' value | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `mandate_import_entries` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `record_identifier` | string \| null | Yes | A unique identifier for this entry, which you can use (once the import has been processed by GoCardless) to identify the records that have been created. Limited to 255 characters. | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `links` | object | Yes | Related resources | | `processing_errors` | object \| null | Yes | Per-resource processing errors | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## mandate-pdf URL: https://docs.gocardless.com/docs/api-reference/mandate-pdf # Mandate Pdf Source: https://docs.gocardless.com/docs/api-reference/mandate-pdf ## Create a mandate PDF `POST /mandate_pdfs` Generates a PDF mandate and returns its temporary URL. Customer and bank account details can be left blank (for a blank mandate), provided manually, or inferred from the ID of an existing [mandate](#core-endpoints-mandates). By default, we'll generate PDF mandates in English. To generate a PDF mandate in another language, set the `Accept-Language` header when creating the PDF mandate to the relevant [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code supported for the scheme. | Scheme | Supported languages | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | | ACH | English (`en`) | | Autogiro | English (`en`), Swedish (`sv`) | | Bacs | English (`en`) | | BECS | English (`en`) | | BECS NZ | English (`en`) | | Betalingsservice | Danish (`da`), English (`en`) | | PAD | English (`en`) | | SEPA Core | Danish (`da`), Dutch (`nl`), English (`en`), French (`fr`), German (`de`), Italian (`it`), Portuguese (`pt`), Spanish (`es`), Swedish (`sv`) | ### Request body Wrap request body attributes in a `mandate_pdfs` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `scheme` | string \| null | No | Direct Debit scheme. Can be supplied or automatically detected from the bank account details provided. If you do not provide a scheme, you must provide either a mandate, an `iban`, or [local details](#appendix-local-bank-details) including a `country_code`. | | `country_code` | string \| null | No | [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) alpha-2 code. Required if providing local details. | | `iban` | string \| null | No | International Bank Account Number. Alternatively you can provide [local details](#appendix-local-bank-details). IBANs cannot be provided for Autogiro mandates. | | `bic` | string \| null | No | SWIFT BIC. Will be derived automatically if a valid `iban` or [local details](#appendix-local-bank-details) are provided. | | `account_number` | string \| null | No | Bank account number - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `bank_code` | string \| null | No | Bank code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `branch_code` | string \| null | No | Branch code - see [local details](#appendix-local-bank-details) for more information. Alternatively you can provide an `iban`. | | `account_holder_name` | string \| null | No | Name of the account holder, as known by the bank. Usually this matches the name of the [customer](#core-endpoints-customers). This field cannot exceed 18 characters. | | `given_name` | string \| null | No | The customer's given name (i.e. first name). Used to populate the "Customer Name or Company name" field on the PDF. Ignored if `company_name` is provided. | | `family_name` | string \| null | No | The customer's family name (i.e. last name). Used to populate the "Customer Name or Company name" field on the PDF. Ignored if `company_name` is provided. | | `company_name` | string \| null | No | The customer's company name. Used to populate the "Customer Name or Company name" field on the PDF. | | `mandate_reference` | string \| null | No | Unique 6 to 18 character reference. This may be left blank at the point of signing. | | `signature_date` | string \| null | No | If provided, a form will be generated with this date and no signature field. | | `phone_number` | string \| null | No | The customer phone number. Should only be provided for BECS NZ mandates. | | `swedish_identity_number` | string \| null | No | For Swedish customers only. The civic/company number (personnummer, samordningsnummer, or organisationsnummer) of the customer. Should only be supplied for Autogiro mandates. | | `danish_identity_number` | string \| null | No | For Danish customers only. The civic/company number (CPR or CVR) of the customer. Should only be supplied for Betalingsservice mandates. | | `address_line1` | string \| null | No | The first line of the customer's address. | | `address_line2` | string \| null | No | The second line of the customer's address. | | `address_line3` | string \| null | No | The third line of the customer's address. | | `city` | string \| null | No | The city of the customer's address. | | `region` | string \| null | No | The customer's address region, county or department. For US customers a 2 letter [ISO3166-2:US](https://en.wikipedia.org/wiki/ISO_3166-2:US) state code is required (e.g. `CA` for California). | | `postal_code` | string \| null | No | The customer's postal code. | | `account_type` | enum \| null | No | Bank account type. Required for USD-denominated bank accounts. Must not be provided for bank accounts in other currencies. See [local details](#local-bank-details-united-states) for more information. | | `payer_ip_address` | string \| null | No | For American customers only. IP address of the computer used by the customer to set up the mandate. This is required in order to create compliant Mandate PDFs according to the ACH scheme rules. | | `subscription_amount` | string / integer | No | For American customers only. Subscription amount being authorised by the mandate. In the lowest denomination for the currency (cents in USD). Is required if `subscription_frequency` has been provided. | | `subscription_frequency` | enum \| null | No | For American customers only. Frequency of the subscription being authorised by the mandate. One of `weekly`, `monthly` or `yearly`. Is required if `subscription_amount` has been provided. | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `mandate_pdfs` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `url` | string | No | The URL at which this mandate PDF can be viewed until it expires at the date and time specified by `expires_at`. You should not store this URL or rely on its structure remaining the same. | | `expires_at` | string | No | The date and time at which the `url` will expire (10 minutes after the original request). | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## negative-balance-limit URL: https://docs.gocardless.com/docs/api-reference/negative-balance-limit # Negative Balance Limit Source: https://docs.gocardless.com/docs/api-reference/negative-balance-limit ## List negative balance limits `GET /negative_balance_limits` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of negative balance limits.

Restricted: This endpoint is restricted to GoCardless Embed customers. Please [contact us](https://forms.gocardless.com/l/305971/2023-01-25/535t8n){:target="_blank"} if you are interested in using this product.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `currency` | query | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `creditor` | query | string | No | Unique identifier, beginning with "CR". | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `negative_balance_limits` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "NBL". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this limit was created. | | `balance_limit` | integer | Yes | The limit amount in pence (e.g. 10000 for a -100 GBP limit). | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `links` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## outbound-payment URL: https://docs.gocardless.com/docs/api-reference/outbound-payment # Outbound Payment Source: https://docs.gocardless.com/docs/api-reference/outbound-payment ## Create an outbound payment `POST /outbound_payments` ### Request body Wrap request body attributes in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | Yes | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `description` | string | No | A human-readable description of the outbound payment | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier of the outbound payment. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the outbound payment was created. | | `status` | enum | No | One of: - `verifying`: The payment has been [created](#outbound-payments-create-an-outbound-payment) and the verification process has begun. - `pending_approval`: The payment is awaiting [approval](#outbound-payments-approve-an-outbound-payment). - `scheduled`: The payment has passed verification & [approval](#outbound-payments-approve-an-outbound-payment), but processing has not yet begun. - `executing`: The execution date has arrived and the payment has been placed in queue for processing. - `executed`: The payment has been accepted by the scheme and is now on its way to the recipient. - `cancelled`: The payment has been [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not [approved](#outbound-payments-approve-an-outbound-payment) on time. - `failed`: The payment was not sent, usually due to an error while or after executing. | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency. Currently only "GBP" is supported. | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `description` | string | No | A human-readable description of the outbound payment | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `is_withdrawal` | boolean | No | Indicates whether the outbound payment is a withdrawal to your verified business bank account. | | `links` | object | No | | | `verifications` | object \| null | No | Contains details of the verifications performed for the outbound payment | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List outbound payments `GET /outbound_payments` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of outbound payments. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_from` | query | string | No | The beginning of query period | | `created_to` | query | string | No | The end of query period | | `status` | query | | No | | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `outbound_payments` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier of the outbound payment. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the outbound payment was created. | | `status` | enum | No | One of: - `verifying`: The payment has been [created](#outbound-payments-create-an-outbound-payment) and the verification process has begun. - `pending_approval`: The payment is awaiting [approval](#outbound-payments-approve-an-outbound-payment). - `scheduled`: The payment has passed verification & [approval](#outbound-payments-approve-an-outbound-payment), but processing has not yet begun. - `executing`: The execution date has arrived and the payment has been placed in queue for processing. - `executed`: The payment has been accepted by the scheme and is now on its way to the recipient. - `cancelled`: The payment has been [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not [approved](#outbound-payments-approve-an-outbound-payment) on time. - `failed`: The payment was not sent, usually due to an error while or after executing. | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency. Currently only "GBP" is supported. | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `description` | string | No | A human-readable description of the outbound payment | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `is_withdrawal` | boolean | No | Indicates whether the outbound payment is a withdrawal to your verified business bank account. | | `links` | object | No | | | `verifications` | object \| null | No | Contains details of the verifications performed for the outbound payment | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Create a withdrawal outbound payment `POST /outbound_payments/withdrawal` Creates an outbound payment to your verified business bank account as the recipient. ### Request body Wrap request body attributes in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | Yes | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `description` | string | No | A human-readable description of the outbound payment | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier of the outbound payment. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the outbound payment was created. | | `status` | enum | No | One of: - `verifying`: The payment has been [created](#outbound-payments-create-an-outbound-payment) and the verification process has begun. - `pending_approval`: The payment is awaiting [approval](#outbound-payments-approve-an-outbound-payment). - `scheduled`: The payment has passed verification & [approval](#outbound-payments-approve-an-outbound-payment), but processing has not yet begun. - `executing`: The execution date has arrived and the payment has been placed in queue for processing. - `executed`: The payment has been accepted by the scheme and is now on its way to the recipient. - `cancelled`: The payment has been [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not [approved](#outbound-payments-approve-an-outbound-payment) on time. - `failed`: The payment was not sent, usually due to an error while or after executing. | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency. Currently only "GBP" is supported. | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `description` | string | No | A human-readable description of the outbound payment | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `is_withdrawal` | boolean | No | Indicates whether the outbound payment is a withdrawal to your verified business bank account. | | `links` | object | No | | | `verifications` | object \| null | No | Contains details of the verifications performed for the outbound payment | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Cancel an outbound payment `POST /outbound_payments/{outbound_payment_id}/actions/cancel` Cancels an outbound payment. Only outbound payments with either `verifying`, `pending_approval`, or `scheduled` status can be cancelled. Once an outbound payment is `executing`, the money moving process has begun and cannot be reversed. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `outbound_payment_id` | path | string | Yes | The outbound payment id | ### Request body Wrap request body attributes in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier of the outbound payment. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the outbound payment was created. | | `status` | enum | No | One of: - `verifying`: The payment has been [created](#outbound-payments-create-an-outbound-payment) and the verification process has begun. - `pending_approval`: The payment is awaiting [approval](#outbound-payments-approve-an-outbound-payment). - `scheduled`: The payment has passed verification & [approval](#outbound-payments-approve-an-outbound-payment), but processing has not yet begun. - `executing`: The execution date has arrived and the payment has been placed in queue for processing. - `executed`: The payment has been accepted by the scheme and is now on its way to the recipient. - `cancelled`: The payment has been [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not [approved](#outbound-payments-approve-an-outbound-payment) on time. - `failed`: The payment was not sent, usually due to an error while or after executing. | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency. Currently only "GBP" is supported. | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `description` | string | No | A human-readable description of the outbound payment | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `is_withdrawal` | boolean | No | Indicates whether the outbound payment is a withdrawal to your verified business bank account. | | `links` | object | No | | | `verifications` | object \| null | No | Contains details of the verifications performed for the outbound payment | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Approve an outbound payment `POST /outbound_payments/{outbound_payment_id}/actions/approve` Approves an outbound payment. Only outbound payments with the "pending_approval" status can be approved. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `outbound_payment_id` | path | string | Yes | The outbound payment id | ### Request body Wrap request body attributes in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier of the outbound payment. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the outbound payment was created. | | `status` | enum | No | One of: - `verifying`: The payment has been [created](#outbound-payments-create-an-outbound-payment) and the verification process has begun. - `pending_approval`: The payment is awaiting [approval](#outbound-payments-approve-an-outbound-payment). - `scheduled`: The payment has passed verification & [approval](#outbound-payments-approve-an-outbound-payment), but processing has not yet begun. - `executing`: The execution date has arrived and the payment has been placed in queue for processing. - `executed`: The payment has been accepted by the scheme and is now on its way to the recipient. - `cancelled`: The payment has been [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not [approved](#outbound-payments-approve-an-outbound-payment) on time. - `failed`: The payment was not sent, usually due to an error while or after executing. | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency. Currently only "GBP" is supported. | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `description` | string | No | A human-readable description of the outbound payment | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `is_withdrawal` | boolean | No | Indicates whether the outbound payment is a withdrawal to your verified business bank account. | | `links` | object | No | | | `verifications` | object \| null | No | Contains details of the verifications performed for the outbound payment | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get an outbound payment `GET /outbound_payments/{outbound_payment_id}` Fetches an outbound_payment by ID ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `outbound_payment_id` | path | string | Yes | The outbound payment id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier of the outbound payment. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the outbound payment was created. | | `status` | enum | No | One of: - `verifying`: The payment has been [created](#outbound-payments-create-an-outbound-payment) and the verification process has begun. - `pending_approval`: The payment is awaiting [approval](#outbound-payments-approve-an-outbound-payment). - `scheduled`: The payment has passed verification & [approval](#outbound-payments-approve-an-outbound-payment), but processing has not yet begun. - `executing`: The execution date has arrived and the payment has been placed in queue for processing. - `executed`: The payment has been accepted by the scheme and is now on its way to the recipient. - `cancelled`: The payment has been [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not [approved](#outbound-payments-approve-an-outbound-payment) on time. - `failed`: The payment was not sent, usually due to an error while or after executing. | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency. Currently only "GBP" is supported. | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `description` | string | No | A human-readable description of the outbound payment | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `is_withdrawal` | boolean | No | Indicates whether the outbound payment is a withdrawal to your verified business bank account. | | `links` | object | No | | | `verifications` | object \| null | No | Contains details of the verifications performed for the outbound payment | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update an outbound payment `PUT /outbound_payments/{outbound_payment_id}` Updates an outbound payment object. This accepts only the metadata parameter. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `outbound_payment_id` | path | string | Yes | The outbound payment id | ### Request body Wrap request body attributes in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier of the outbound payment. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when the outbound payment was created. | | `status` | enum | No | One of: - `verifying`: The payment has been [created](#outbound-payments-create-an-outbound-payment) and the verification process has begun. - `pending_approval`: The payment is awaiting [approval](#outbound-payments-approve-an-outbound-payment). - `scheduled`: The payment has passed verification & [approval](#outbound-payments-approve-an-outbound-payment), but processing has not yet begun. - `executing`: The execution date has arrived and the payment has been placed in queue for processing. - `executed`: The payment has been accepted by the scheme and is now on its way to the recipient. - `cancelled`: The payment has been [cancelled](#outbound-payments-cancel-an-outbound-payment) or was not [approved](#outbound-payments-approve-an-outbound-payment) on time. - `failed`: The payment was not sent, usually due to an error while or after executing. | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `currency` | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency. Currently only "GBP" is supported. | | `execution_date` | string | No | A future date on which the outbound payment should be sent. If not specified, the payment will be sent as soon as possible. | | `description` | string | No | A human-readable description of the outbound payment | | `reference` | string | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
Faster Payments - 18 characters, including: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 &-./"
| | `is_withdrawal` | boolean | No | Indicates whether the outbound payment is a withdrawal to your verified business bank account. | | `links` | object | No | | | `verifications` | object \| null | No | Contains details of the verifications performed for the outbound payment | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Outbound payment statistics `GET /outbound_payments/stats` Retrieve aggregate statistics on outbound payments. ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `pending_approval_amount` | integer | No | The amount sum of outbound payments with status `pending_approval`. | | `pending_approval_count` | integer | No | The number of outbound payments with status `pending_approval`. | | `scheduled_amount` | integer | No | The amount sum of outbound payments with status `scheduled`. | | `scheduled_count` | integer | No | The number of outbound payments with status `scheduled`. | | `executing_amount` | integer | No | The amount sum of outbound payments with status `executing`. | | `executing_count` | integer | No | The number of outbound payments with status `executing`. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## outbound-payment-import URL: https://docs.gocardless.com/docs/api-reference/outbound-payment-import # Outbound Payment Import Source: https://docs.gocardless.com/docs/api-reference/outbound-payment-import ## Create an outbound payment import `POST /outbound_payment_imports` ### Request body Wrap request body attributes in a `outbound_payment_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `entry_items` | array | Yes | | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payment_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "IM". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | The status of the outbound payment import. - `created`: The initial state of a new import. - `validating`: Import validation in progress. - `invalid`: Import validation failed. - `valid`: Import validation succeeded. - `processing`: Authorisation received; payments are being generated. - `processed`: All entries have been successfully converted into outbound payments. - `cancelled`: The import was cancelled by a user or automatically expired by the system. | | `amount_sum` | integer | No | The sum of all import entry amounts, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | | No | | | `authorisation_url` | string | No | The link to the GoCardless dashboard to review and authorise the import | | `entry_counts` | object | No | | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List outbound payment imports `GET /outbound_payment_imports` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your outbound payment imports. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `status` | query | | No | | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `outbound_payment_imports` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "IM". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | The status of the outbound payment import. - `created`: The initial state of a new import. - `validating`: Import validation in progress. - `invalid`: Import validation failed. - `valid`: Import validation succeeded. - `processing`: Authorisation received; payments are being generated. - `processed`: All entries have been successfully converted into outbound payments. - `cancelled`: The import was cancelled by a user or automatically expired by the system. | | `amount_sum` | integer | No | The sum of all import entry amounts, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | | No | | | `authorisation_url` | string | No | The link to the GoCardless dashboard to review and authorise the import | | `entry_counts` | object | No | | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get an outbound payment import `GET /outbound_payment_imports/{outbound_payment_import_id}` Returns a single outbound payment import. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `outbound_payment_import_id` | path | string | Yes | The outbound payment import id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `outbound_payment_imports` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "IM". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `status` | enum | No | The status of the outbound payment import. - `created`: The initial state of a new import. - `validating`: Import validation in progress. - `invalid`: Import validation failed. - `valid`: Import validation succeeded. - `processing`: Authorisation received; payments are being generated. - `processed`: All entries have been successfully converted into outbound payments. - `cancelled`: The import was cancelled by a user or automatically expired by the system. | | `amount_sum` | integer | No | The sum of all import entry amounts, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | | No | | | `authorisation_url` | string | No | The link to the GoCardless dashboard to review and authorise the import | | `entry_counts` | object | No | | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## outbound-payment-import-entry URL: https://docs.gocardless.com/docs/api-reference/outbound-payment-import-entry # Outbound Payment Import Entry Source: https://docs.gocardless.com/docs/api-reference/outbound-payment-import-entry ## List outbound payment import entries `GET /outbound_payment_import_entries` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of the entries for a given outbound payment import. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `outbound_payment_import` | query | string | Yes | Unique identifier, beginning with "IM". | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `outbound_payment_import_entries` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "IE". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `processed_at` | string \| null | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this entry was processed. | | `amount` | integer \| null | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `scheme` | enum | No | Bank payment scheme to process the outbound payment. Currently only "faster_payments" (GBP) is supported. | | `reference` | string \| null | No | An optional reference for the outbound payment. | | `verification_result` | enum \| null | No | The result of bank account holder verification, if performed. | | `validation_errors` | object \| null | No | Per-field validation errors for this entry, keyed by resource type and then by field name. | | `links` | object | No | | | `metadata` | object \| null | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## payer-authorisation URL: https://docs.gocardless.com/docs/api-reference/payer-authorisation # Payer Authorisation Source: https://docs.gocardless.com/docs/api-reference/payer-authorisation ## Get a single Payer Authorisation `GET /payer_authorisations/{payer_authorisation_id}` Retrieves the details of a single existing Payer Authorisation. It can be used for polling the status of a Payer Authorisation. **Deprecated:** Payer Authorisation is legacy API and cannot be used by new integrators. The [Billing Request](#billing-requests) API should be used for any new integrations. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payer_authorisation_id` | path | string | Yes | The payer authorisation id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payer_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PA". | | `created_at` | string \| null | Yes | [Timestamp](#api-usage-dates-and-times), recording when this Payer Authorisation was created. | | `customer` | object | Yes | All details required for the creation of a [Customer](#core-endpoints-customers). | | `bank_account` | object | Yes | All details required for the creation of a [Customer Bank Account](#core-endpoints-customer-bank-accounts). | | `mandate` | object | Yes | All details required for the creation of a [Mandate](#core-endpoints-mandates). | | `incomplete_fields` | array | Yes | An array of fields which are missing and is required to set up the mandate. | | `links` | object | Yes | IDs of the created resources. Available after the Payer Authorisation is completed. | | `status` | enum | Yes | One of: - `created`: The PayerAuthorisation has been created, and not been confirmed yet - `submitted`: The payer information has been submitted - `confirmed`: PayerAuthorisation is confirmed and resources are ready to be created - `completed`: The PayerAuthorisation has been completed and customer, bank_account and mandate has been created - `failed`: The PayerAuthorisation has failed and customer, bank_account and mandate is not created | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a Payer Authorisation `PUT /payer_authorisations/{payer_authorisation_id}` Updates a Payer Authorisation. Updates the Payer Authorisation with the request data. Can be invoked as many times as needed. Only fields present in the request will be modified. An empty array of incomplete_fields means that the resource is valid. This endpoint has been designed this way so you do not need to save any payer data on your servers or the browser while still being able to implement a progressive solution, such a multi-step form.

Note that in order to update the `metadata` attribute values it must be sent completely as it overrides the previously existing values.

**Deprecated:** Payer Authorisation is legacy API and cannot be used by new integrators. The [Billing Request](#billing-requests) API should be used for any new integrations. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payer_authorisation_id` | path | string | Yes | The payer authorisation id | ### Request body Wrap request body attributes in a `payer_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `customer` | object | Yes | All details required for the creation of a [Customer](#core-endpoints-customers). | | `bank_account` | object | Yes | All details required for the creation of a [Customer Bank Account](#core-endpoints-customer-bank-accounts). | | `mandate` | object | Yes | All details required for the creation of a [Mandate](#core-endpoints-mandates). | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payer_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PA". | | `created_at` | string \| null | Yes | [Timestamp](#api-usage-dates-and-times), recording when this Payer Authorisation was created. | | `customer` | object | Yes | All details required for the creation of a [Customer](#core-endpoints-customers). | | `bank_account` | object | Yes | All details required for the creation of a [Customer Bank Account](#core-endpoints-customer-bank-accounts). | | `mandate` | object | Yes | All details required for the creation of a [Mandate](#core-endpoints-mandates). | | `incomplete_fields` | array | Yes | An array of fields which are missing and is required to set up the mandate. | | `links` | object | Yes | IDs of the created resources. Available after the Payer Authorisation is completed. | | `status` | enum | Yes | One of: - `created`: The PayerAuthorisation has been created, and not been confirmed yet - `submitted`: The payer information has been submitted - `confirmed`: PayerAuthorisation is confirmed and resources are ready to be created - `completed`: The PayerAuthorisation has been completed and customer, bank_account and mandate has been created - `failed`: The PayerAuthorisation has failed and customer, bank_account and mandate is not created | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Create a Payer Authorisation `POST /payer_authorisations` Creates a Payer Authorisation. The resource is saved to the database even if incomplete. An empty array of incomplete_fields means that the resource is valid. The ID of the resource is used for the other actions. This endpoint has been designed this way so you do not need to save any payer data on your servers or the browser while still being able to implement a progressive solution, such as a multi-step form. **Deprecated:** Payer Authorisation is legacy API and cannot be used by new integrators. The [Billing Request](#billing-requests) API should be used for any new integrations. ### Request body Wrap request body attributes in a `payer_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `customer` | object | Yes | All details required for the creation of a [Customer](#core-endpoints-customers). | | `bank_account` | object | Yes | All details required for the creation of a [Customer Bank Account](#core-endpoints-customer-bank-accounts). | | `mandate` | object | Yes | All details required for the creation of a [Mandate](#core-endpoints-mandates). | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payer_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PA". | | `created_at` | string \| null | Yes | [Timestamp](#api-usage-dates-and-times), recording when this Payer Authorisation was created. | | `customer` | object | Yes | All details required for the creation of a [Customer](#core-endpoints-customers). | | `bank_account` | object | Yes | All details required for the creation of a [Customer Bank Account](#core-endpoints-customer-bank-accounts). | | `mandate` | object | Yes | All details required for the creation of a [Mandate](#core-endpoints-mandates). | | `incomplete_fields` | array | Yes | An array of fields which are missing and is required to set up the mandate. | | `links` | object | Yes | IDs of the created resources. Available after the Payer Authorisation is completed. | | `status` | enum | Yes | One of: - `created`: The PayerAuthorisation has been created, and not been confirmed yet - `submitted`: The payer information has been submitted - `confirmed`: PayerAuthorisation is confirmed and resources are ready to be created - `completed`: The PayerAuthorisation has been completed and customer, bank_account and mandate has been created - `failed`: The PayerAuthorisation has failed and customer, bank_account and mandate is not created | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Submit a Payer Authorisation `POST /payer_authorisations/{payer_authorisation_id}/actions/submit` Submits all the data previously pushed to this PayerAuthorisation for verification. This time, a 200 HTTP status is returned if the resource is valid and a 422 error response in case of validation errors. After it is successfully submitted, the Payer Authorisation can no longer be edited. **Deprecated:** Payer Authorisation is legacy API and cannot be used by new integrators. The [Billing Request](#billing-requests) API should be used for any new integrations. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payer_authorisation_id` | path | string | Yes | The payer authorisation id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payer_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PA". | | `created_at` | string \| null | Yes | [Timestamp](#api-usage-dates-and-times), recording when this Payer Authorisation was created. | | `customer` | object | Yes | All details required for the creation of a [Customer](#core-endpoints-customers). | | `bank_account` | object | Yes | All details required for the creation of a [Customer Bank Account](#core-endpoints-customer-bank-accounts). | | `mandate` | object | Yes | All details required for the creation of a [Mandate](#core-endpoints-mandates). | | `incomplete_fields` | array | Yes | An array of fields which are missing and is required to set up the mandate. | | `links` | object | Yes | IDs of the created resources. Available after the Payer Authorisation is completed. | | `status` | enum | Yes | One of: - `created`: The PayerAuthorisation has been created, and not been confirmed yet - `submitted`: The payer information has been submitted - `confirmed`: PayerAuthorisation is confirmed and resources are ready to be created - `completed`: The PayerAuthorisation has been completed and customer, bank_account and mandate has been created - `failed`: The PayerAuthorisation has failed and customer, bank_account and mandate is not created | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Confirm a Payer Authorisation `POST /payer_authorisations/{payer_authorisation_id}/actions/confirm` Confirms the Payer Authorisation, indicating that the resources are ready to be created. A Payer Authorisation cannot be confirmed if it hasn't been submitted yet.

The main use of the confirm endpoint is to enable integrators to acknowledge the end of the setup process. They might want to make the payers go through some other steps after they go through our flow or make them go through the necessary verification mechanism (upcoming feature).

**Deprecated:** Payer Authorisation is legacy API and cannot be used by new integrators. The [Billing Request](#billing-requests) API should be used for any new integrations. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payer_authorisation_id` | path | string | Yes | The payer authorisation id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payer_authorisations` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PA". | | `created_at` | string \| null | Yes | [Timestamp](#api-usage-dates-and-times), recording when this Payer Authorisation was created. | | `customer` | object | Yes | All details required for the creation of a [Customer](#core-endpoints-customers). | | `bank_account` | object | Yes | All details required for the creation of a [Customer Bank Account](#core-endpoints-customer-bank-accounts). | | `mandate` | object | Yes | All details required for the creation of a [Mandate](#core-endpoints-mandates). | | `incomplete_fields` | array | Yes | An array of fields which are missing and is required to set up the mandate. | | `links` | object | Yes | IDs of the created resources. Available after the Payer Authorisation is completed. | | `status` | enum | Yes | One of: - `created`: The PayerAuthorisation has been created, and not been confirmed yet - `submitted`: The payer information has been submitted - `confirmed`: PayerAuthorisation is confirmed and resources are ready to be created - `completed`: The PayerAuthorisation has been completed and customer, bank_account and mandate has been created - `failed`: The PayerAuthorisation has failed and customer, bank_account and mandate is not created | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## payer-theme URL: https://docs.gocardless.com/docs/api-reference/payer-theme # Payer Theme Source: https://docs.gocardless.com/docs/api-reference/payer-theme ## Create a payer theme associated with a creditor `POST /branding/payer_themes` Creates a new payer theme associated with a creditor. If a creditor already has payer themes, this will update the existing payer theme linked to the creditor.

Restricted: This endpoint is restricted to GoCardless Embed customers. Please [contact us](https://forms.gocardless.com/l/305971/2023-01-25/535t8n){:target="_blank"} if you are interested in using this product.

### Request body Wrap request body attributes in a `payer_themes` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `header_background_colour` | string | No | Colour for header background (hexcode) | | `link_text_colour` | string | No | Colour for text links (hexcode) | | `button_background_colour` | string | No | Colour for buttons background (hexcode) | | `content_box_border_colour` | string | No | Colour for content box border (hexcode) | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payer_themes` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "PTH". | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## payment URL: https://docs.gocardless.com/docs/api-reference/payment # Payment Source: https://docs.gocardless.com/docs/api-reference/payment ## Create a payment `POST /payments` Creates a new payment object. This fails with a `mandate_is_inactive` error if the linked [mandate](#core-endpoints-mandates) is cancelled or has failed. Payments can be created against mandates with status of: `pending_customer_approval`, `pending_submission`, `submitted`, and `active`.

Warning: in Bacs, you have the option to provide a payment reference up to 10 characters in length. However, if you are providing custom mandate references (which can only be enabled by contacting support), the combined length of the two references separated by a dash character must not exceed 18 characters. Payment references may be up to 140 characters for SEPA, 11 for Autogiro and 30 for Betalingsservice, irrespective of the mandate reference.

### Request body Wrap request body attributes in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `amount` | string / integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Minimum and maximum amounts vary by payment scheme. For more information, see [Transaction limits](https://support.gocardless.com/hc/en-gb/articles/115000309245-Transaction-limits) For Variable Recurring Payments (VRP), this must not exceed the mandate's `max_amount_per_payment` constraint. | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `description` | string \| null | No | A human-readable description of the payment. This will be included in the notification email GoCardless sends to your customer if your organisation does not send its own notifications (see [compliance requirements](#appendix-compliance-requirements)). | | `charge_date` | string \| null | No | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | | `reference` | string \| null | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `app_fee` | string / integer | No | The amount to be deducted from the payment as the OAuth app's fee, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `retry_if_possible` | boolean | No | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `faster_ach` | boolean \| null | No | Set this to true or false in the request to create an ACH payment to explicitly choose whether the payment should be processed through Faster ACH or standard ACH, rather than relying on the presence or absence of the charge date to indicate that. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `psu_interaction_type` | enum | No | Indicates how a Variable Recurring Payment (VRP) is initiated, by or on behalf of the payer. - `in_session`: The payer is actively participating in the payment creation session. - `off_session`: The payer is not present during the transaction, and the payment is initiated by the merchant based on an established consent (e.g., a recurring subscription payment). | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Minimum and maximum amounts vary by payment scheme. For more information, see [Transaction limits](https://support.gocardless.com/hc/en-gb/articles/115000309245-Transaction-limits) For Variable Recurring Payments (VRP), this must not exceed the mandate's `max_amount_per_payment` constraint. | | `amount_refunded` | integer | Yes | Amount [refunded](#core-endpoints-refunds), in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `description` | string \| null | Yes | A human-readable description of the payment. This will be included in the notification email GoCardless sends to your customer if your organisation does not send its own notifications (see [compliance requirements](#appendix-compliance-requirements)). | | `charge_date` | string \| null | Yes | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | Yes | One of: - `pending_customer_approval`: we're waiting for the customer to approve this payment - `pending_submission`: the payment has been created, but not yet submitted to the banks - `submitted`: the payment has been submitted to the banks - `confirmed`: the payment has been confirmed as collected - `paid_out`: the payment has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the payment has been cancelled - `customer_approval_denied`: the customer has denied approval for the payment. You should contact the customer directly - `failed`: the payment failed to be processed. Note that payments can fail after being confirmed if the failure message is sent late by the banks. - `charged_back`: the payment has been charged back | | `app_fee` | integer \| null | No | The amount to be deducted from the payment as the OAuth app''s fee, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Only present if the payment was created via an app. | | `links` | object | Yes | | | `faster_ach` | boolean \| null | No | This field indicates whether the ACH payment is processed through Faster ACH or standard ACH. It is only present in the API response for ACH payments. | | `fx` | object | Yes | | | `retry_if_possible` | boolean | Yes | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `scheme` | string \| null | Yes | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to", "sepa_core", "sepa_credit_transfer" and "sepa_instant_credit_transfer" are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List payments `GET /payments` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your payments. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `currency` | query | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `charge_date` | query | object | No | | | `customer` | query | | No | | | `sort_field` | query | | No | | | `sort_direction` | query | enum | No | The direction to sort in. One of: - `asc` - `desc` | | `creditor` | query | | No | | | `subscription` | query | string | No | Unique identifier, beginning with "SB". | | `mandate` | query | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `status` | query | enum | No | One of: - `pending_customer_approval`: we're waiting for the customer to approve this payment - `pending_submission`: the payment has been created, but not yet submitted to the banks - `submitted`: the payment has been submitted to the banks - `confirmed`: the payment has been confirmed as collected - `paid_out`: the payment has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the payment has been cancelled - `customer_approval_denied`: the customer has denied approval for the payment. You should contact the customer directly - `failed`: the payment failed to be processed. Note that payments can fail after being confirmed if the failure message is sent late by the banks. - `charged_back`: the payment has been charged back | | `scheme` | query | string \| null | No | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to", "sepa_core", "sepa_credit_transfer" and "sepa_instant_credit_transfer" are supported. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `payments` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Minimum and maximum amounts vary by payment scheme. For more information, see [Transaction limits](https://support.gocardless.com/hc/en-gb/articles/115000309245-Transaction-limits) For Variable Recurring Payments (VRP), this must not exceed the mandate's `max_amount_per_payment` constraint. | | `amount_refunded` | integer | Yes | Amount [refunded](#core-endpoints-refunds), in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `description` | string \| null | Yes | A human-readable description of the payment. This will be included in the notification email GoCardless sends to your customer if your organisation does not send its own notifications (see [compliance requirements](#appendix-compliance-requirements)). | | `charge_date` | string \| null | Yes | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | Yes | One of: - `pending_customer_approval`: we're waiting for the customer to approve this payment - `pending_submission`: the payment has been created, but not yet submitted to the banks - `submitted`: the payment has been submitted to the banks - `confirmed`: the payment has been confirmed as collected - `paid_out`: the payment has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the payment has been cancelled - `customer_approval_denied`: the customer has denied approval for the payment. You should contact the customer directly - `failed`: the payment failed to be processed. Note that payments can fail after being confirmed if the failure message is sent late by the banks. - `charged_back`: the payment has been charged back | | `app_fee` | integer \| null | No | The amount to be deducted from the payment as the OAuth app''s fee, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Only present if the payment was created via an app. | | `links` | object | Yes | | | `faster_ach` | boolean \| null | No | This field indicates whether the ACH payment is processed through Faster ACH or standard ACH. It is only present in the API response for ACH payments. | | `fx` | object | Yes | | | `retry_if_possible` | boolean | Yes | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `scheme` | string \| null | Yes | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to", "sepa_core", "sepa_credit_transfer" and "sepa_instant_credit_transfer" are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single payment `GET /payments/{payment_id}` Retrieves the details of a single existing payment. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payment_id` | path | string | Yes | The payment id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Minimum and maximum amounts vary by payment scheme. For more information, see [Transaction limits](https://support.gocardless.com/hc/en-gb/articles/115000309245-Transaction-limits) For Variable Recurring Payments (VRP), this must not exceed the mandate's `max_amount_per_payment` constraint. | | `amount_refunded` | integer | Yes | Amount [refunded](#core-endpoints-refunds), in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `description` | string \| null | Yes | A human-readable description of the payment. This will be included in the notification email GoCardless sends to your customer if your organisation does not send its own notifications (see [compliance requirements](#appendix-compliance-requirements)). | | `charge_date` | string \| null | Yes | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | Yes | One of: - `pending_customer_approval`: we're waiting for the customer to approve this payment - `pending_submission`: the payment has been created, but not yet submitted to the banks - `submitted`: the payment has been submitted to the banks - `confirmed`: the payment has been confirmed as collected - `paid_out`: the payment has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the payment has been cancelled - `customer_approval_denied`: the customer has denied approval for the payment. You should contact the customer directly - `failed`: the payment failed to be processed. Note that payments can fail after being confirmed if the failure message is sent late by the banks. - `charged_back`: the payment has been charged back | | `app_fee` | integer \| null | No | The amount to be deducted from the payment as the OAuth app''s fee, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Only present if the payment was created via an app. | | `links` | object | Yes | | | `faster_ach` | boolean \| null | No | This field indicates whether the ACH payment is processed through Faster ACH or standard ACH. It is only present in the API response for ACH payments. | | `fx` | object | Yes | | | `retry_if_possible` | boolean | Yes | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `scheme` | string \| null | Yes | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to", "sepa_core", "sepa_credit_transfer" and "sepa_instant_credit_transfer" are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a payment `PUT /payments/{payment_id}` Updates a payment object. This accepts only the metadata parameter. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payment_id` | path | string | Yes | The payment id | ### Request body Wrap request body attributes in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `retry_if_possible` | boolean | No | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Minimum and maximum amounts vary by payment scheme. For more information, see [Transaction limits](https://support.gocardless.com/hc/en-gb/articles/115000309245-Transaction-limits) For Variable Recurring Payments (VRP), this must not exceed the mandate's `max_amount_per_payment` constraint. | | `amount_refunded` | integer | Yes | Amount [refunded](#core-endpoints-refunds), in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `description` | string \| null | Yes | A human-readable description of the payment. This will be included in the notification email GoCardless sends to your customer if your organisation does not send its own notifications (see [compliance requirements](#appendix-compliance-requirements)). | | `charge_date` | string \| null | Yes | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | Yes | One of: - `pending_customer_approval`: we're waiting for the customer to approve this payment - `pending_submission`: the payment has been created, but not yet submitted to the banks - `submitted`: the payment has been submitted to the banks - `confirmed`: the payment has been confirmed as collected - `paid_out`: the payment has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the payment has been cancelled - `customer_approval_denied`: the customer has denied approval for the payment. You should contact the customer directly - `failed`: the payment failed to be processed. Note that payments can fail after being confirmed if the failure message is sent late by the banks. - `charged_back`: the payment has been charged back | | `app_fee` | integer \| null | No | The amount to be deducted from the payment as the OAuth app''s fee, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Only present if the payment was created via an app. | | `links` | object | Yes | | | `faster_ach` | boolean \| null | No | This field indicates whether the ACH payment is processed through Faster ACH or standard ACH. It is only present in the API response for ACH payments. | | `fx` | object | Yes | | | `retry_if_possible` | boolean | Yes | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `scheme` | string \| null | Yes | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to", "sepa_core", "sepa_credit_transfer" and "sepa_instant_credit_transfer" are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Cancel a payment `POST /payments/{payment_id}/actions/cancel` Cancels the payment if it has not already been submitted to the banks. Any metadata supplied to this endpoint will be stored on the payment cancellation event it causes. This will fail with a `cancellation_failed` error unless the payment's status is `pending_submission`. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payment_id` | path | string | Yes | The payment id | ### Request body Wrap request body attributes in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Minimum and maximum amounts vary by payment scheme. For more information, see [Transaction limits](https://support.gocardless.com/hc/en-gb/articles/115000309245-Transaction-limits) For Variable Recurring Payments (VRP), this must not exceed the mandate's `max_amount_per_payment` constraint. | | `amount_refunded` | integer | Yes | Amount [refunded](#core-endpoints-refunds), in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `description` | string \| null | Yes | A human-readable description of the payment. This will be included in the notification email GoCardless sends to your customer if your organisation does not send its own notifications (see [compliance requirements](#appendix-compliance-requirements)). | | `charge_date` | string \| null | Yes | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | Yes | One of: - `pending_customer_approval`: we're waiting for the customer to approve this payment - `pending_submission`: the payment has been created, but not yet submitted to the banks - `submitted`: the payment has been submitted to the banks - `confirmed`: the payment has been confirmed as collected - `paid_out`: the payment has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the payment has been cancelled - `customer_approval_denied`: the customer has denied approval for the payment. You should contact the customer directly - `failed`: the payment failed to be processed. Note that payments can fail after being confirmed if the failure message is sent late by the banks. - `charged_back`: the payment has been charged back | | `app_fee` | integer \| null | No | The amount to be deducted from the payment as the OAuth app''s fee, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Only present if the payment was created via an app. | | `links` | object | Yes | | | `faster_ach` | boolean \| null | No | This field indicates whether the ACH payment is processed through Faster ACH or standard ACH. It is only present in the API response for ACH payments. | | `fx` | object | Yes | | | `retry_if_possible` | boolean | Yes | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `scheme` | string \| null | Yes | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to", "sepa_core", "sepa_credit_transfer" and "sepa_instant_credit_transfer" are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Retry a payment `POST /payments/{payment_id}/actions/retry` Retries a failed payment if the underlying mandate is active. You will receive a `resubmission_requested` webhook, but after that retrying the payment follows the same process as its initial creation, so you will receive a `submitted` webhook, followed by a `confirmed` or `failed` event. Any metadata supplied to this endpoint will be stored against the payment submission event it causes. This will return a `retry_failed` error if the payment has not failed. Payments can be retried up to 3 times. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payment_id` | path | string | Yes | The payment id | ### Request body Wrap request body attributes in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `charge_date` | string \| null | No | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payments` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PM". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Minimum and maximum amounts vary by payment scheme. For more information, see [Transaction limits](https://support.gocardless.com/hc/en-gb/articles/115000309245-Transaction-limits) For Variable Recurring Payments (VRP), this must not exceed the mandate's `max_amount_per_payment` constraint. | | `amount_refunded` | integer | Yes | Amount [refunded](#core-endpoints-refunds), in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `description` | string \| null | Yes | A human-readable description of the payment. This will be included in the notification email GoCardless sends to your customer if your organisation does not send its own notifications (see [compliance requirements](#appendix-compliance-requirements)). | | `charge_date` | string \| null | Yes | A future date on which the payment should be collected. If not specified, the payment will be collected as soon as possible. If the value is before the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date` creation will fail. If the value is not a working day it will be rolled forwards to the next available one. | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | Yes | One of: - `pending_customer_approval`: we're waiting for the customer to approve this payment - `pending_submission`: the payment has been created, but not yet submitted to the banks - `submitted`: the payment has been submitted to the banks - `confirmed`: the payment has been confirmed as collected - `paid_out`: the payment has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the payment has been cancelled - `customer_approval_denied`: the customer has denied approval for the payment. You should contact the customer directly - `failed`: the payment failed to be processed. Note that payments can fail after being confirmed if the failure message is sent late by the banks. - `charged_back`: the payment has been charged back | | `app_fee` | integer \| null | No | The amount to be deducted from the payment as the OAuth app''s fee, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). Only present if the payment was created via an app. | | `links` | object | Yes | | | `faster_ach` | boolean \| null | No | This field indicates whether the ACH payment is processed through Faster ACH or standard ACH. It is only present in the API response for ACH payments. | | `fx` | object | Yes | | | `retry_if_possible` | boolean | Yes | On failure, automatically retry the payment using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `scheme` | string \| null | Yes | A bank payment scheme. Currently "ach", "autogiro", "bacs", "becs", "becs_nz", "betalingsservice", "faster_payments", "pad", "pay_to", "sepa_core", "sepa_credit_transfer" and "sepa_instant_credit_transfer" are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## payment-account URL: https://docs.gocardless.com/docs/api-reference/payment-account # Payment Account Source: https://docs.gocardless.com/docs/api-reference/payment-account ## Get a single payment account details `GET /payment_accounts/{payment_account_id}` Retrieves the details of an existing payment account. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payment_account_id` | path | string | Yes | The payment account id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payment_accounts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. Usually this is the same as the name stored with the linked [creditor](#core-endpoints-creditors). This field will be transliterated, upcased and truncated to 18 characters. | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `links` | object | No | | | `account_balance` | integer | No | Current balance on a payment account in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). It is time-sensitive as it is ever changing. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List payment accounts `GET /payment_accounts` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your payment accounts. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `payment_accounts` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "BA". | | `account_holder_name` | string | No | Name of the account holder, as known by the bank. Usually this is the same as the name stored with the linked [creditor](#core-endpoints-creditors). This field will be transliterated, upcased and truncated to 18 characters. | | `account_number_ending` | string \| null | No | The last few digits of the account number. Currently 4 digits for NZD bank accounts and 2 digits for other currencies. | | `currency` | string \| null | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `bank_name` | string \| null | No | Name of bank, taken from the bank details. | | `links` | object | No | | | `account_balance` | integer | No | Current balance on a payment account in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). It is time-sensitive as it is ever changing. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## payment-account-transaction URL: https://docs.gocardless.com/docs/api-reference/payment-account-transaction # Payment Account Transaction Source: https://docs.gocardless.com/docs/api-reference/payment-account-transaction ## Get a single payment account transaction `GET /payment_account_transactions/{payment_account_transaction_id}` Retrieves the details of an existing payment account transaction. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payment_account_transaction_id` | path | string | Yes | The payment account transaction id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payment_account_transactions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | The unique ID of the payment account transaction. | | `value_date` | string | No | The date of when the transaction occurred. | | `reference` | string | No | The reference of the transaction. This is typically supplied by the sender. | | `description` | string | No | The description of the transaction, if available | | `counterparty_name` | string | No | The name of the counterparty of the transaction. The counterparty is the recipient for a credit, or the sender for a debit. | | `links` | object | No | | | `currency` | enum | No | The currency of the transaction. | | `direction` | enum | No | The direction of the transaction. Debits mean money leaving the account (e.g. outbound payment), while credits signify money coming in (e.g. manual top-up). | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `balance_after_transaction` | integer | No | Balance after transaction, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List payment account transactions `GET /payment_accounts/{payment_account_transaction_id}/transactions` List transactions for a given payment account. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payment_account_transaction_id` | path | string | Yes | The payment account transaction id | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `value_date_from` | query | string | Yes | The beginning of query period | | `value_date_to` | query | string | Yes | The end of query period | | `direction` | query | enum | No | The direction of the transaction. Debits mean money leaving the account (e.g. outbound payment), while credits signify money coming in (e.g. manual top-up). | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `payment_account_transactions` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | The unique ID of the payment account transaction. | | `value_date` | string | No | The date of when the transaction occurred. | | `reference` | string | No | The reference of the transaction. This is typically supplied by the sender. | | `description` | string | No | The description of the transaction, if available | | `counterparty_name` | string | No | The name of the counterparty of the transaction. The counterparty is the recipient for a credit, or the sender for a debit. | | `links` | object | No | | | `currency` | enum | No | The currency of the transaction. | | `direction` | enum | No | The direction of the transaction. Debits mean money leaving the account (e.g. outbound payment), while credits signify money coming in (e.g. manual top-up). | | `amount` | integer | No | Amount, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `balance_after_transaction` | integer | No | Balance after transaction, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## payout URL: https://docs.gocardless.com/docs/api-reference/payout # Payout Source: https://docs.gocardless.com/docs/api-reference/payout ## List payouts `GET /payouts` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your payouts. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `creditor` | query | string | No | Unique identifier, beginning with "CR". | | `creditor_bank_account` | query | string | No | Unique identifier, beginning with "BA". | | `currency` | query | enum | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `status` | query | enum | No | One of: - `pending`: the payout has been created, but not yet sent to your bank or it is in the process of being exchanged through our FX provider. - `paid`: the payout has been sent to the your bank. FX payouts will become `paid` after we emit the `fx_rate_confirmed` webhook. - `bounced`: the payout bounced when sent, the payout can be retried. | | `reference` | query | string | No | Reference which appears on the creditor's bank statement. | | `payout_type` | query | enum | No | Whether a payout contains merchant revenue or partner fees. | | `metadata` | query | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `payouts` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PO". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `deducted_fees` | integer | Yes | Fees that have already been deducted from the payout amount in minor unit (e.g. pence in GBP, cents in EUR), inclusive of tax if applicable.
For each `late_failure_settled` or `chargeback_settled` action, we refund the transaction fees in a payout. This means that a payout can have a negative `deducted_fees` value.
This field is calculated as `(GoCardless fees + app fees + surcharge fees) - (refunded fees)`
If the merchant is invoiced for fees separately from the payout, then `deducted_fees` will be 0. | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `reference` | string | Yes | Reference which appears on the creditor's bank statement. | | `status` | enum | Yes | One of: - `pending`: the payout has been created, but not yet sent to your bank or it is in the process of being exchanged through our FX provider. - `paid`: the payout has been sent to the your bank. FX payouts will become `paid` after we emit the `fx_rate_confirmed` webhook. - `bounced`: the payout bounced when sent, the payout can be retried. | | `payout_type` | enum | Yes | Whether a payout contains merchant revenue or partner fees. | | `arrival_date` | string \| null | Yes | Date the payout is due to arrive in the creditor's bank account. One of: - `yyyy-mm-dd`: the payout has been paid and is due to arrive in the creditor's bank account on this day - `null`: the payout hasn't been paid yet | | `links` | object | Yes | | | `fx` | object | Yes | | | `tax_currency` | string \| null | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) code for the currency in which tax is paid out to the tax authorities of your tax jurisdiction. Currently “EUR”, “GBP”, for French or British merchants, this will be `null` if tax is not applicable beta | | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single payout `GET /payouts/{payout_id}` Retrieves the details of a single payout. For an example of how to reconcile the transactions in a payout, see [this guide](#events-reconciling-payouts-with-events). ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payout_id` | path | string | Yes | The payout id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payouts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PO". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `deducted_fees` | integer | Yes | Fees that have already been deducted from the payout amount in minor unit (e.g. pence in GBP, cents in EUR), inclusive of tax if applicable.
For each `late_failure_settled` or `chargeback_settled` action, we refund the transaction fees in a payout. This means that a payout can have a negative `deducted_fees` value.
This field is calculated as `(GoCardless fees + app fees + surcharge fees) - (refunded fees)`
If the merchant is invoiced for fees separately from the payout, then `deducted_fees` will be 0. | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `reference` | string | Yes | Reference which appears on the creditor's bank statement. | | `status` | enum | Yes | One of: - `pending`: the payout has been created, but not yet sent to your bank or it is in the process of being exchanged through our FX provider. - `paid`: the payout has been sent to the your bank. FX payouts will become `paid` after we emit the `fx_rate_confirmed` webhook. - `bounced`: the payout bounced when sent, the payout can be retried. | | `payout_type` | enum | Yes | Whether a payout contains merchant revenue or partner fees. | | `arrival_date` | string \| null | Yes | Date the payout is due to arrive in the creditor's bank account. One of: - `yyyy-mm-dd`: the payout has been paid and is due to arrive in the creditor's bank account on this day - `null`: the payout hasn't been paid yet | | `links` | object | Yes | | | `fx` | object | Yes | | | `tax_currency` | string \| null | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) code for the currency in which tax is paid out to the tax authorities of your tax jurisdiction. Currently “EUR”, “GBP”, for French or British merchants, this will be `null` if tax is not applicable beta | | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a payout `PUT /payouts/{payout_id}` Updates a payout object. This accepts only the metadata parameter. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `payout_id` | path | string | Yes | The payout id | ### Request body Wrap request body attributes in a `payouts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `payouts` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "PO". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `deducted_fees` | integer | Yes | Fees that have already been deducted from the payout amount in minor unit (e.g. pence in GBP, cents in EUR), inclusive of tax if applicable.
For each `late_failure_settled` or `chargeback_settled` action, we refund the transaction fees in a payout. This means that a payout can have a negative `deducted_fees` value.
This field is calculated as `(GoCardless fees + app fees + surcharge fees) - (refunded fees)`
If the merchant is invoiced for fees separately from the payout, then `deducted_fees` will be 0. | | `currency` | enum | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `reference` | string | Yes | Reference which appears on the creditor's bank statement. | | `status` | enum | Yes | One of: - `pending`: the payout has been created, but not yet sent to your bank or it is in the process of being exchanged through our FX provider. - `paid`: the payout has been sent to the your bank. FX payouts will become `paid` after we emit the `fx_rate_confirmed` webhook. - `bounced`: the payout bounced when sent, the payout can be retried. | | `payout_type` | enum | Yes | Whether a payout contains merchant revenue or partner fees. | | `arrival_date` | string \| null | Yes | Date the payout is due to arrive in the creditor's bank account. One of: - `yyyy-mm-dd`: the payout has been paid and is due to arrive in the creditor's bank account on this day - `null`: the payout hasn't been paid yet | | `links` | object | Yes | | | `fx` | object | Yes | | | `tax_currency` | string \| null | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) code for the currency in which tax is paid out to the tax authorities of your tax jurisdiction. Currently “EUR”, “GBP”, for French or British merchants, this will be `null` if tax is not applicable beta | | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## payout-item URL: https://docs.gocardless.com/docs/api-reference/payout-item # Payout Item Source: https://docs.gocardless.com/docs/api-reference/payout-item ## Get all payout items in a single payout `GET /payout_items` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of items in the payout. This endpoint only serves requests for payouts created in the last 6 months. Requests for older payouts will return an HTTP status 410 Gone. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `payout` | query | string | Yes | Unique identifier, beginning with "PO". | | `include_2020_tax_cutover` | query | enum | No | Boolean value indicating whether the API should return tax data for the cutover period of April to August 2020. Defaults to false. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `payout_items` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `amount` | string | Yes | The positive (credit) or negative (debit) value of the item, in fractional currency; the lowest denomination for the currency (e.g. pence in GBP, cents in EUR), to one decimal place.

For accuracy, we store some of our fees to greater precision than we can actually pay out (for example, a GoCardless fee we record might come to 0.5 pence, but it is not possible to send a payout via bank transfer including a half penny).

To calculate the final amount of the payout, we sum all of the items and then round to the nearest currency unit.

| | `type` | enum | Yes | The type of the credit (positive) or debit (negative) item in the payout (inclusive of VAT if applicable). One of: - `payment_paid_out` (credit) - `payment_failed` (debit): The payment failed to be processed. - `payment_charged_back` (debit): The payment has been charged back. - `payment_refunded` (debit): The payment has been refunded to the customer. - `refund` (debit): A refund sent to a customer, not linked to a payment. - `refund_funds_returned` (credit): The refund could not be sent to the customer, and the funds have been returned to you. - `gocardless_fee` (credit/debit): The fees that GoCardless charged for a payment. In the case of a payment failure or chargeback, these will appear as credits. Will include taxes if applicable for merchants. - `app_fee` (credit/debit): The optional fees that a partner may have taken for a payment. In the case of a payment failure or chargeback, these will appear as credits. - `revenue_share` (credit/debit): A share of the fees that GoCardless collected which some partner integrations receive when their users take payments. Only shown in partner payouts. In the case of a payment failure or chargeback, these will appear as credits. - `surcharge_fee` (credit/debit): GoCardless deducted a surcharge fee as the payment failed or was charged back, or refunded a surcharge fee as the bank or customer cancelled the chargeback. Will include taxes if applicable for merchants. | | `taxes` | array | Yes | An array of tax items beta _Note_: VAT applies to transaction and surcharge fees for merchants operating in the UK and France. | | `links` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## redirect-flow URL: https://docs.gocardless.com/docs/api-reference/redirect-flow # Redirect Flow Source: https://docs.gocardless.com/docs/api-reference/redirect-flow ## Create a redirect flow `POST /redirect_flows` Creates a redirect flow object which can then be used to redirect your customer to the GoCardless hosted payment pages. **Deprecated:** Redirect Flows are legacy APIs and cannot be used by new integrators. The [Billing Request flow](#billing-requests) API should be used for your payment flows. ### Request body Wrap request body attributes in a `redirect_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `description` | string \| null | No | A description of the item the customer is paying for. This will be shown on the hosted payment pages. | | `session_token` | string | Yes | The customer's session ID must be provided when the redirect flow is set up and again when it is completed. This allows integrators to ensure that the user who was originally sent to the GoCardless payment pages is the one who has completed them. | | `scheme` | enum \| null | No | The Direct Debit scheme of the mandate. If specified, the payment pages will only allow the set-up of a mandate for the specified scheme. It is recommended that you leave this blank so the most appropriate scheme is picked based on the customer's bank account. | | `success_redirect_url` | string | Yes | The URL to redirect to upon successful mandate setup. You must use a URL beginning `https` in the live environment. | | `prefilled_customer` | object | No | Customer information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `prefilled_bank_account` | object | No | Bank account information used to prefill the payment page so your customer doesn't have to re-type details you already hold about them. It will be stored unvalidated and the customer will be able to review and amend it before completing the form. | | `links` | object | No | | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `redirect_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "RE". | | `description` | string \| null | No | A description of the item the customer is paying for. This will be shown on the hosted payment pages. | | `session_token` | string | No | The customer's session ID must be provided when the redirect flow is set up and again when it is completed. This allows integrators to ensure that the user who was originally sent to the GoCardless payment pages is the one who has completed them. | | `scheme` | enum \| null | No | The Direct Debit scheme of the mandate. If specified, the payment pages will only allow the set-up of a mandate for the specified scheme. It is recommended that you leave this blank so the most appropriate scheme is picked based on the customer's bank account. | | `success_redirect_url` | string | No | The URL to redirect to upon successful mandate setup. You must use a URL beginning `https` in the live environment. | | `confirmation_url` | string | No | The URL of a confirmation page, which you may optionally redirect the customer to rather than use your own page, that confirms in their chosen language that their Direct Debit has been set up successfully. Only returned once the customer has set up their mandate via the payment pages and the redirect flow has been [completed](#redirect-flows-complete-a-redirect-flow), and only available for 15 minutes from when you complete the redirect flow. The structure of this URL may change at any time, so you should read it directly from the API response. | | `redirect_url` | string | No | The URL of the hosted payment pages for this redirect flow. This is the URL you should redirect your customer to. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `links` | object | No | | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | | `mandate_reference` | string | No | Mandate reference generated by GoCardless or submitted by an integrator. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single redirect flow `GET /redirect_flows/{redirect_flow_id}` Returns all details about a single redirect flow **Deprecated:** Redirect Flows are legacy APIs and cannot be used by new integrators. The [Billing Request flow](#billing-requests) API should be used for your payment flows. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `redirect_flow_id` | path | string | Yes | The redirect flow id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `redirect_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "RE". | | `description` | string \| null | No | A description of the item the customer is paying for. This will be shown on the hosted payment pages. | | `session_token` | string | No | The customer's session ID must be provided when the redirect flow is set up and again when it is completed. This allows integrators to ensure that the user who was originally sent to the GoCardless payment pages is the one who has completed them. | | `scheme` | enum \| null | No | The Direct Debit scheme of the mandate. If specified, the payment pages will only allow the set-up of a mandate for the specified scheme. It is recommended that you leave this blank so the most appropriate scheme is picked based on the customer's bank account. | | `success_redirect_url` | string | No | The URL to redirect to upon successful mandate setup. You must use a URL beginning `https` in the live environment. | | `confirmation_url` | string | No | The URL of a confirmation page, which you may optionally redirect the customer to rather than use your own page, that confirms in their chosen language that their Direct Debit has been set up successfully. Only returned once the customer has set up their mandate via the payment pages and the redirect flow has been [completed](#redirect-flows-complete-a-redirect-flow), and only available for 15 minutes from when you complete the redirect flow. The structure of this URL may change at any time, so you should read it directly from the API response. | | `redirect_url` | string | No | The URL of the hosted payment pages for this redirect flow. This is the URL you should redirect your customer to. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `links` | object | No | | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | | `mandate_reference` | string | No | Mandate reference generated by GoCardless or submitted by an integrator. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Complete a redirect flow `POST /redirect_flows/{redirect_flow_id}/actions/complete` This creates a [customer](#core-endpoints-customers), [customer bank account](#core-endpoints-customer-bank-accounts), and [mandate](#core-endpoints-mandates) using the details supplied by your customer and returns the ID of the created mandate. This will return a `redirect_flow_incomplete` error if your customer has not yet been redirected back to your site, and a `redirect_flow_already_completed` error if your integration has already completed this flow. It will return a `bad_request` error if the `session_token` differs to the one supplied when the redirect flow was created. **Deprecated:** Redirect Flows are legacy APIs and cannot be used by new integrators. The [Billing Request flow](#billing-requests) API should be used for your payment flows. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `redirect_flow_id` | path | string | Yes | The redirect flow id | ### Request body Wrap request body attributes in a `redirect_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `session_token` | string | Yes | The customer's session ID must be provided when the redirect flow is set up and again when it is completed. This allows integrators to ensure that the user who was originally sent to the GoCardless payment pages is the one who has completed them. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `redirect_flows` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "RE". | | `description` | string \| null | No | A description of the item the customer is paying for. This will be shown on the hosted payment pages. | | `session_token` | string | No | The customer's session ID must be provided when the redirect flow is set up and again when it is completed. This allows integrators to ensure that the user who was originally sent to the GoCardless payment pages is the one who has completed them. | | `scheme` | enum \| null | No | The Direct Debit scheme of the mandate. If specified, the payment pages will only allow the set-up of a mandate for the specified scheme. It is recommended that you leave this blank so the most appropriate scheme is picked based on the customer's bank account. | | `success_redirect_url` | string | No | The URL to redirect to upon successful mandate setup. You must use a URL beginning `https` in the live environment. | | `confirmation_url` | string | No | The URL of a confirmation page, which you may optionally redirect the customer to rather than use your own page, that confirms in their chosen language that their Direct Debit has been set up successfully. Only returned once the customer has set up their mandate via the payment pages and the redirect flow has been [completed](#redirect-flows-complete-a-redirect-flow), and only available for 15 minutes from when you complete the redirect flow. The structure of this URL may change at any time, so you should read it directly from the API response. | | `redirect_url` | string | No | The URL of the hosted payment pages for this redirect flow. This is the URL you should redirect your customer to. | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `links` | object | No | | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. _Note:_ This should not be used for storing PII data. | | `mandate_reference` | string | No | Mandate reference generated by GoCardless or submitted by an integrator. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## refund URL: https://docs.gocardless.com/docs/api-reference/refund # Refund Source: https://docs.gocardless.com/docs/api-reference/refund ## Create a refund `POST /refunds` Creates a new refund object. This fails with: - `total_amount_confirmation_invalid` if the confirmation amount doesn't match the total amount refunded for the payment. This safeguard is there to prevent two processes from creating refunds without awareness of each other. - `available_refund_amount_insufficient` if the creditor does not have sufficient balance for refunds available to cover the cost of the requested refund.

Restricted: This endpoint is disabled by default. To enable it, you will need to enable refunds on your GoCardless Dashboard.

Warning: A payment that has been (partially) refunded can still receive a late failure or chargeback from the customer's bank.

A refund can only be created once it is outside the safer refund period (7 calendar days after the charge date) otherwise an error is returned. The safer refund period can be disabled by contacting GoCardless.

### Request body Wrap request body attributes in a `refunds` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `amount` | string / integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `reference` | string \| null | No | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `total_amount_confirmation` | string / integer | No | Total expected refunded amount in minor unit (e.g. pence/cents/öre). If there are other partial refunds against this payment, this value should be the sum of the existing refunds plus the amount of the refund being created.
Must be supplied if `links[payment]` is present.

It is possible to opt out of requiring total_amount_confirmation, please contact our support team for more information.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `refunds` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "RF". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `currency` | string | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. This is set to the currency of the refund's [payment](#core-endpoints-payments). | | `status` | enum | Yes | One of: - `created`: the refund has been created - `pending_submission`: the refund has been created, but not yet submitted to the banks - `submitted`: the refund has been submitted to the banks - `paid`: the refund has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the refund has been cancelled - `bounced`: the refund has failed to be paid - `funds_returned`: the refund has had its funds returned | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | | `fx` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List refunds `GET /refunds` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your refunds. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `payment` | query | string | No | Unique identifier, beginning with "PM". | | `mandate` | query | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `refund_type` | query | enum | No | Whether a refund was issued against a mandate or a payment. One of: - `payment`: default returns refunds created against payments only - `mandate`: returns refunds created against mandates only | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `refunds` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "RF". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `currency` | string | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. This is set to the currency of the refund's [payment](#core-endpoints-payments). | | `status` | enum | Yes | One of: - `created`: the refund has been created - `pending_submission`: the refund has been created, but not yet submitted to the banks - `submitted`: the refund has been submitted to the banks - `paid`: the refund has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the refund has been cancelled - `bounced`: the refund has failed to be paid - `funds_returned`: the refund has had its funds returned | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | | `fx` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single refund `GET /refunds/{refund_id}` Retrieves all details for a single refund ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `refund_id` | path | string | Yes | The refund id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `refunds` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "RF". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `currency` | string | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. This is set to the currency of the refund's [payment](#core-endpoints-payments). | | `status` | enum | Yes | One of: - `created`: the refund has been created - `pending_submission`: the refund has been created, but not yet submitted to the banks - `submitted`: the refund has been submitted to the banks - `paid`: the refund has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the refund has been cancelled - `bounced`: the refund has failed to be paid - `funds_returned`: the refund has had its funds returned | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | | `fx` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a refund `PUT /refunds/{refund_id}` Updates a refund object. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `refund_id` | path | string | Yes | The refund id | ### Request body Wrap request body attributes in a `refunds` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `refunds` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, beginning with "RF". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | Yes | Amount in minor unit (e.g. pence in GBP, cents in EUR). | | `currency` | string | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. This is set to the currency of the refund's [payment](#core-endpoints-payments). | | `status` | enum | Yes | One of: - `created`: the refund has been created - `pending_submission`: the refund has been created, but not yet submitted to the banks - `submitted`: the refund has been submitted to the banks - `paid`: the refund has been included in a [payout](#core-endpoints-payouts) - `cancelled`: the refund has been cancelled - `bounced`: the refund has failed to be paid - `funds_returned`: the refund has had its funds returned | | `reference` | string \| null | Yes | An optional reference that will appear on your customer's bank statement. The character limit for this reference is dependent on the scheme.
ACH - 10 characters
Autogiro - 11 characters
Bacs - 10 characters
BECS - 30 characters
BECS NZ - 12 characters
Betalingsservice - 30 characters
Faster Payments - 18 characters
PAD - scheme doesn't offer references
PayTo - 18 characters
SEPA - 140 characters
Note that this reference must be unique (for each merchant) for the BECS scheme as it is a scheme requirement.

Restricted: You can only specify a payment reference for Bacs payments (that is, when collecting from the UK) if you're on the GoCardless Plus, Pro or Enterprise packages.

Restricted: You can not specify a payment reference for Faster Payments.

| | `metadata` | object | Yes | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `links` | object | Yes | | | `fx` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## scenario-simulator URL: https://docs.gocardless.com/docs/api-reference/scenario-simulator # Scenario Simulator Source: https://docs.gocardless.com/docs/api-reference/scenario-simulator ## Simulate a scenario `POST /scenario_simulators/{scenario_simulator_id}/actions/run` Runs the specific scenario simulator against the specific resource ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `scenario_simulator_id` | path | string | Yes | The scenario simulator id | ### Request body Wrap request body attributes in a `scenario_simulators` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `scenario_simulators` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | The unique identifier of the simulator, used to initiate simulations. One of: - `creditor_verification_status_action_required`: Sets a creditor's `verification status` to `action required`, meaning that the creditor must provide further information to GoCardless in order to verify their account to receive payouts. - `creditor_verification_status_in_review`: Sets a creditor's `verification status` to `in review`, meaning that the creditor has provided all of the information requested by GoCardless to verify their account, and is now awaiting review. - `creditor_verification_status_successful`: Sets a creditor's `verification status` to `successful`, meaning that the creditor is fully verified and can receive payouts. - `payment_confirmed`: Transitions a payment through to `confirmed`. It must start in the `pending_submission` state, and its mandate must be in the `activated` state (unless it is a payment for ACH, BECS, BECS_NZ or SEPA, in which cases the mandate may be `pending_submission`, since their mandates are submitted with their first payment). - `payment_paid_out`: Transitions a payment through to `paid_out`, having been collected successfully and paid out to you. It must start in the `pending_submission` state, and its mandate must be in the `activated` state (unless it is a payment for ACH, BECS, BECS_NZ or SEPA, in which cases the mandate may be `pending_submission`, since their mandates are submitted with their first payment). - `payment_failed`: Transitions a payment through to `failed`. It must start in the `pending_submission` state, and its mandate must be in the `activated` state (unless it is a payment for ACH, BECS, BECS_NZ or SEPA, in which cases the mandate may be `pending_submission`, since their mandates are submitted with their first payment). - `payment_charged_back`: Behaves the same as the `payout_paid_out` simulator, except that the payment is transitioned to `charged_back` after it is paid out, having been charged back by the customer. - `payment_chargeback_settled`: Behaves the same as the `payment_charged_back` simulator, except that the charged back payment is additionally included as a debit item in a payout, thereby settling the charged back payment. - `payment_late_failure`: Transitions a payment through to `late_failure`, having been apparently collected successfully beforehand. It must start in either the `pending_submission` or `paid_out` state, and its mandate must be in the `activated` state (unless it is a payment for ACH, BECS, BECS_NZ or SEPA, in which cases the mandate may be `pending_submission`, since their mandates are submitted with their first payment). Not compatible with Autogiro mandates. - `payment_late_failure_settled`: Behaves the same as the `payment_late_failure` simulator, except that the late failure is additionally included as a debit item in a payout, thereby settling the late failure. - `payment_submitted`: Transitions a payment to `submitted`, without proceeding any further. It must start in the `pending_submission` state. - `mandate_activated`: Transitions a mandate through to `activated`, having been submitted to the banks and set up successfully. It must start in the `pending_submission` state. Not compatible with ACH, BECS, BECS_NZ and SEPA mandates, which are submitted and activated with their first payment. - `mandate_customer_approval_granted`: Transitions a mandate through to `pending_submission`, as if the customer approved the mandate creation. It must start in the `pending_customer_approval` state. Compatible only with Bacs and SEPA mandates, which support customer signatures on the mandate. All payments associated with the mandate will be transitioned to `pending_submission`. All subscriptions associated with the mandate will become `active`. - `mandate_customer_approval_skipped`: Transitions a mandate through to `pending_submission`, as if the customer skipped the mandate approval during the mandate creation process. It must start in the `pending_customer_approval` state. Compatible only with Bacs and SEPA mandates, which support customer signatures on the mandate. All payments associated with the mandate will be transitioned to `pending_submission`. All subscriptions associated with the mandate will become `active`. - `mandate_failed`: Transitions a mandate through to `failed`, having been submitted to the banks but found to be invalid (for example due to invalid bank details). It must start in the `pending_submission` or `submitted` states. Not compatible with SEPA mandates, which are submitted with their first payment. - `mandate_expired`: Transitions a mandate through to `expired`, having been submitted to the banks, set up successfully and then expired because no collection attempts were made against it for longer than the scheme's dormancy period (13 months for Bacs, 3 years for SEPA, 15 months for ACH, Betalingsservice, and BECS). It must start in the `pending_submission` state. Not compatible with Autogiro, BECS NZ, and PAD mandates, which do not expire. - `mandate_transferred`: Transitions a mandate through to `transferred`, having been submitted to the banks, set up successfully and then moved to a new bank account due. It must start in the `pending_submission` state. Only compatible with Bacs and SEPA mandates. - `mandate_transferred_with_resubmission`: Transitions a mandate through `transferred` and resubmits it to the banks, can be caused be the UK's Current Account Switching Service (CASS) or when a customer contacts GoCardless to change their bank details. It must start in the `pending_submission` state. Only compatible with Bacs mandates. - `mandate_suspended_by_payer`: Transitions a mandate to `suspended_by_payer`, as if payer has suspended the mandate after it has been setup successfully. It must start in the `activated` state. Only compatible with PAY_TO mandates. - `refund_paid`: Transitions a refund to `paid`. It must start in either the `pending_submission` or `submitted` state. - `refund_settled`: Transitions a refund to `paid`, if it's not already, then generates a payout that includes the refund, thereby settling the funds. It must start in one of `pending_submission`, `submitted` or `paid` states. - `refund_bounced`: Transitions a refund to `bounced`. It must start in either the `pending_submission`, `submitted`, or `paid` state. - `refund_returned`: Transitions a refund to `refund_returned`. The refund must start in `pending_submission`. - `payout_bounced`: Transitions a payout to `bounced`. It must start in the `paid` state. - `billing_request_fulfilled`: Authorises the billing request, and then fulfils it. The billing request must be in the `pending` state, with all actions completed except for `bank_authorisation`. Only billing requests with a `payment_request` are supported. - `billing_request_fulfilled_and_payment_failed`: Authorises the billing request, fulfils it, and moves the associated payment to `failed`. The billing request must be in the `pending` state, with all actions completed except for `bank_authorisation`. Only billing requests with a `payment_request` are supported. - `billing_request_fulfilled_and_payment_confirmed_to_failed`: Authorises the billing request, fulfils it, moves the associated payment to `confirmed` and then moves it to `failed`. The billing request must be in the `pending` state, with all actions completed except for `bank_authorisation`. Only billing requests with a `payment_request` are supported. - `billing_request_fulfilled_and_payment_paid_out`: Authorises the billing request, fulfils it, and moves the associated payment to `paid_out`. The billing request must be in the `pending` state, with all actions completed except for `bank_authorisation`. Only billing requests with a `payment_request` are supported. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## scheme-identifier URL: https://docs.gocardless.com/docs/api-reference/scheme-identifier # Scheme Identifier Source: https://docs.gocardless.com/docs/api-reference/scheme-identifier ## Create a scheme identifier `POST /scheme_identifiers` Creates a new scheme identifier. The scheme identifier status will be `pending` while GoCardless is processing the request. Once the scheme identifier is ready to be used the status will be updated to `active`. At this point, GoCardless will emit a scheme identifier activated event via webhook to notify you of this change. In Bacs, it will take up to five working days for a scheme identifier to become active. On other schemes, including SEPA, this happens instantly. #### Scheme identifier name validations The `name` field of a scheme identifier can contain alphanumeric characters, spaces and special characters. Its maximum length and the special characters it supports depend on the scheme: | __scheme__ | __maximum length__ | __special characters allowed__ | | :---------------- | :----------------- | :-------------------------------------------------- | | `bacs` | 18 characters | `/` `.` `&` `-` | | `sepa` | 70 characters | `/` `?` `:` `(` `)` `.` `,` `+` `&` `<` `>` `'` `"` | | `ach` | 16 characters | `/` `?` `:` `(` `)` `.` `,` `'` `+` `-` | | `faster_payments` | 18 characters | `/` `?` `:` `(` `)` `.` `,` `'` `+` `-` | The validation error that gets returned for an invalid name will contain a suggested name in the metadata that is guaranteed to pass name validations. You should ensure that the name you set matches the legal name or the trading name of the creditor, otherwise, there is an increased risk of chargeback.

Restricted: This endpoint is restricted to GoCardless Embed customers. Please [contact us](https://forms.gocardless.com/l/305971/2023-01-25/535t8n){:target="_blank"} if you are interested in using this product.

### Request body Wrap request body attributes in a `scheme_identifiers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | The name which appears on customers' bank statements. This should usually be the merchant's trading name. | | `scheme` | enum | Yes | The scheme which this scheme identifier applies to. | | `links` | object | No | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `scheme_identifiers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, usually beginning with "SU". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `name` | string | Yes | The name which appears on customers' bank statements. This should usually be the merchant's trading name. | | `scheme` | enum | Yes | The scheme which this scheme identifier applies to. | | `reference` | string \| null | Yes | The scheme-unique identifier against which payments are submitted. | | `status` | enum | Yes | The status of the scheme identifier. Only `active` scheme identifiers will be applied to a creditor and used against payments. | | `minimum_advance_notice` | integer | Yes | The minimum interval, in working days, between the sending of a pre-notification to the customer, and the charge date of a payment using this scheme identifier. By default, GoCardless sends these notifications automatically. Please see our [compliance requirements](#appendix-compliance-requirements) for more details. | | `can_specify_mandate_reference` | boolean | Yes | Whether a custom reference can be submitted for mandates using this scheme identifier. | | `currency` | enum | Yes | The currency of the scheme identifier. | | `address_line1` | string \| null | Yes | The first line of the scheme identifier's support address. | | `address_line2` | string \| null | Yes | The second line of the scheme identifier's support address. | | `address_line3` | string \| null | Yes | The third line of the scheme identifier's support address. | | `city` | string \| null | Yes | The city of the scheme identifier's support address. | | `region` | string \| null | Yes | The scheme identifier's support address region, county or department. | | `postal_code` | string \| null | Yes | The scheme identifier's support postal code. | | `country_code` | string \| null | Yes | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `email` | string \| null | Yes | Scheme identifier's support email address. | | `phone_number` | string \| null | Yes | Scheme identifier's support phone number. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List scheme identifiers `GET /scheme_identifiers` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your scheme identifiers. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `creditor` | query | string | No | Unique identifier, beginning with "CR". | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `scheme_identifiers` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, usually beginning with "SU". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `name` | string | Yes | The name which appears on customers' bank statements. This should usually be the merchant's trading name. | | `scheme` | enum | Yes | The scheme which this scheme identifier applies to. | | `reference` | string \| null | Yes | The scheme-unique identifier against which payments are submitted. | | `status` | enum | Yes | The status of the scheme identifier. Only `active` scheme identifiers will be applied to a creditor and used against payments. | | `minimum_advance_notice` | integer | Yes | The minimum interval, in working days, between the sending of a pre-notification to the customer, and the charge date of a payment using this scheme identifier. By default, GoCardless sends these notifications automatically. Please see our [compliance requirements](#appendix-compliance-requirements) for more details. | | `can_specify_mandate_reference` | boolean | Yes | Whether a custom reference can be submitted for mandates using this scheme identifier. | | `currency` | enum | Yes | The currency of the scheme identifier. | | `address_line1` | string \| null | Yes | The first line of the scheme identifier's support address. | | `address_line2` | string \| null | Yes | The second line of the scheme identifier's support address. | | `address_line3` | string \| null | Yes | The third line of the scheme identifier's support address. | | `city` | string \| null | Yes | The city of the scheme identifier's support address. | | `region` | string \| null | Yes | The scheme identifier's support address region, county or department. | | `postal_code` | string \| null | Yes | The scheme identifier's support postal code. | | `country_code` | string \| null | Yes | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `email` | string \| null | Yes | Scheme identifier's support email address. | | `phone_number` | string \| null | Yes | Scheme identifier's support phone number. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single scheme identifier `GET /scheme_identifiers/{scheme_identifier_id}` Retrieves the details of an existing scheme identifier. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `scheme_identifier_id` | path | string | Yes | The scheme identifier id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `scheme_identifiers` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | Unique identifier, usually beginning with "SU". | | `created_at` | string | Yes | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `name` | string | Yes | The name which appears on customers' bank statements. This should usually be the merchant's trading name. | | `scheme` | enum | Yes | The scheme which this scheme identifier applies to. | | `reference` | string \| null | Yes | The scheme-unique identifier against which payments are submitted. | | `status` | enum | Yes | The status of the scheme identifier. Only `active` scheme identifiers will be applied to a creditor and used against payments. | | `minimum_advance_notice` | integer | Yes | The minimum interval, in working days, between the sending of a pre-notification to the customer, and the charge date of a payment using this scheme identifier. By default, GoCardless sends these notifications automatically. Please see our [compliance requirements](#appendix-compliance-requirements) for more details. | | `can_specify_mandate_reference` | boolean | Yes | Whether a custom reference can be submitted for mandates using this scheme identifier. | | `currency` | enum | Yes | The currency of the scheme identifier. | | `address_line1` | string \| null | Yes | The first line of the scheme identifier's support address. | | `address_line2` | string \| null | Yes | The second line of the scheme identifier's support address. | | `address_line3` | string \| null | Yes | The third line of the scheme identifier's support address. | | `city` | string \| null | Yes | The city of the scheme identifier's support address. | | `region` | string \| null | Yes | The scheme identifier's support address region, county or department. | | `postal_code` | string \| null | Yes | The scheme identifier's support postal code. | | `country_code` | string \| null | Yes | [ISO 3166-1 alpha-2 code.](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) | | `email` | string \| null | Yes | Scheme identifier's support email address. | | `phone_number` | string \| null | Yes | Scheme identifier's support phone number. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## subscription URL: https://docs.gocardless.com/docs/api-reference/subscription # Subscription Source: https://docs.gocardless.com/docs/api-reference/subscription ## Create a subscription `POST /subscriptions` Creates a new subscription object ### Request body Wrap request body attributes in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `amount` | string / integer | Yes | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `count` | string / integer | No | The total number of payments that should be taken by this subscription. | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | string / integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | Yes | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | string / integer | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `currency` | string | Yes | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `app_fee` | string / integer | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "SB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | No | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | integer \| null | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `currency` | string | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `count` | integer \| null | No | The total number of payments that should be taken by this subscription. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending_customer_approval`: the subscription is waiting for customer approval before becoming active - `customer_approval_denied`: the customer did not approve the subscription - `active`: the subscription is currently active and will continue to create payments - `finished`: all of the payments scheduled for creation under this subscription have been created - `cancelled`: the subscription has been cancelled and will no longer create payments - `paused`: the subscription has been paused and will not create payments | | `upcoming_payments` | array | No | Up to 10 upcoming payments with their amounts and charge dates. | | `app_fee` | integer \| null | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `links` | object | No | | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `earliest_charge_date_after_resume` | string \| null | No | The earliest date that will be used as a `charge_date` on payments created for this subscription if it is resumed. Only present for `paused` subscriptions. This value will change over time. | | `parent_plan_paused` | boolean | No | Whether the parent plan of this subscription is paused. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List subscriptions `GET /subscriptions` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your subscriptions. Please note if the subscriptions are related to customers who have been removed, they will not be shown in the response. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `mandate` | query | string | No | Unique identifier, beginning with "MD". Note that this prefix may not apply to mandates created before 2016. | | `customer` | query | string | No | Unique identifier, beginning with "CU". | | `status` | query | | No | Up to 5 of: - `pending_customer_approval` - `customer_approval_denied` - `active` - `finished` - `cancelled` - `paused` Omit entirely to include subscriptions in all states. | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `subscriptions` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "SB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | No | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | integer \| null | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `currency` | string | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `count` | integer \| null | No | The total number of payments that should be taken by this subscription. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending_customer_approval`: the subscription is waiting for customer approval before becoming active - `customer_approval_denied`: the customer did not approve the subscription - `active`: the subscription is currently active and will continue to create payments - `finished`: all of the payments scheduled for creation under this subscription have been created - `cancelled`: the subscription has been cancelled and will no longer create payments - `paused`: the subscription has been paused and will not create payments | | `upcoming_payments` | array | No | Up to 10 upcoming payments with their amounts and charge dates. | | `app_fee` | integer \| null | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `links` | object | No | | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `earliest_charge_date_after_resume` | string \| null | No | The earliest date that will be used as a `charge_date` on payments created for this subscription if it is resumed. Only present for `paused` subscriptions. This value will change over time. | | `parent_plan_paused` | boolean | No | Whether the parent plan of this subscription is paused. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single subscription `GET /subscriptions/{subscription_id}` Retrieves the details of a single subscription. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `subscription_id` | path | string | Yes | The subscription id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "SB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | No | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | integer \| null | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `currency` | string | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `count` | integer \| null | No | The total number of payments that should be taken by this subscription. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending_customer_approval`: the subscription is waiting for customer approval before becoming active - `customer_approval_denied`: the customer did not approve the subscription - `active`: the subscription is currently active and will continue to create payments - `finished`: all of the payments scheduled for creation under this subscription have been created - `cancelled`: the subscription has been cancelled and will no longer create payments - `paused`: the subscription has been paused and will not create payments | | `upcoming_payments` | array | No | Up to 10 upcoming payments with their amounts and charge dates. | | `app_fee` | integer \| null | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `links` | object | No | | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `earliest_charge_date_after_resume` | string \| null | No | The earliest date that will be used as a `charge_date` on payments created for this subscription if it is resumed. Only present for `paused` subscriptions. This value will change over time. | | `parent_plan_paused` | boolean | No | Whether the parent plan of this subscription is paused. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Update a subscription `PUT /subscriptions/{subscription_id}` Updates a subscription object. This fails with: - `validation_failed` if invalid data is provided when attempting to update a subscription. - `subscription_not_active` if the subscription is no longer active. - `subscription_already_ended` if the subscription has taken all payments. - `mandate_payments_require_approval` if the amount is being changed and the mandate requires approval. - `number_of_subscription_amendments_exceeded` error if the subscription amount has already been changed 10 times. - `forbidden` if the amount is being changed, and the subscription was created by an app and you are not authenticated as that app, or if the subscription was not created by an app and you are authenticated as an app - `resource_created_by_another_app` if the app fee is being changed, and the subscription was created by an app other than the app you are authenticated as ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `subscription_id` | path | string | Yes | The subscription id | ### Request body Wrap request body attributes in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `amount` | string / integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `app_fee` | string / integer | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "SB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | No | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | integer \| null | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `currency` | string | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `count` | integer \| null | No | The total number of payments that should be taken by this subscription. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending_customer_approval`: the subscription is waiting for customer approval before becoming active - `customer_approval_denied`: the customer did not approve the subscription - `active`: the subscription is currently active and will continue to create payments - `finished`: all of the payments scheduled for creation under this subscription have been created - `cancelled`: the subscription has been cancelled and will no longer create payments - `paused`: the subscription has been paused and will not create payments | | `upcoming_payments` | array | No | Up to 10 upcoming payments with their amounts and charge dates. | | `app_fee` | integer \| null | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `links` | object | No | | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `earliest_charge_date_after_resume` | string \| null | No | The earliest date that will be used as a `charge_date` on payments created for this subscription if it is resumed. Only present for `paused` subscriptions. This value will change over time. | | `parent_plan_paused` | boolean | No | Whether the parent plan of this subscription is paused. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Pause a subscription `POST /subscriptions/{subscription_id}/actions/pause` Pause a subscription object. No payments will be created until it is resumed. This can only be used when a subscription is collecting a fixed number of payments (created using `count`), when they continue forever (created without `count` or `end_date`) or the subscription is already paused for a number of cycles. When `pause_cycles` is omitted the subscription is paused until the [resume endpoint](#subscriptions-resume-a-subscription) is called. If the subscription is collecting a fixed number of payments, `end_date` will be set to `null`. When paused indefinitely, `upcoming_payments` will be empty. When `pause_cycles` is provided the subscription will be paused for the number of cycles requested. If the subscription is collecting a fixed number of payments, `end_date` will be set to a new value. When paused for a number of cycles, `upcoming_payments` will still contain the upcoming charge dates. This fails with: - `forbidden` if the subscription was created by an app and you are not authenticated as that app, or if the subscription was not created by an app and you are authenticated as an app - `validation_failed` if invalid data is provided when attempting to pause a subscription. - `subscription_paused_cannot_update_cycles` if the subscription is already paused for a number of cycles and the request provides a value for `pause_cycle`. - `subscription_cannot_be_paused` if the subscription cannot be paused. - `subscription_already_ended` if the subscription has taken all payments. - `pause_cycles_must_be_greater_than_or_equal_to` if the provided value for `pause_cycles` cannot be satisfied.

Warning: Please note that any payments that have already been created from this subscription will still be collected unless you manually cancel them.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `subscription_id` | path | string | Yes | The subscription id | ### Request body Wrap request body attributes in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `pause_cycles` | integer \| null | No | The number of cycles to pause a subscription for. A cycle is one duration of `interval` and `interval_unit`. This should be a non zero positive value. For AUD subscriptions with `interval_unit: weekly` the minimum value varies between `3` & `4` because of the [mandatory minimum waiting period](#subscriptions-resume-a-subscription). For NZD subscriptions with `interval_unit: weekly` the minimum value is `2` because of the [mandatory minimum waiting period](#subscriptions-resume-a-subscription). | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "SB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | No | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | integer \| null | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `currency` | string | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `count` | integer \| null | No | The total number of payments that should be taken by this subscription. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending_customer_approval`: the subscription is waiting for customer approval before becoming active - `customer_approval_denied`: the customer did not approve the subscription - `active`: the subscription is currently active and will continue to create payments - `finished`: all of the payments scheduled for creation under this subscription have been created - `cancelled`: the subscription has been cancelled and will no longer create payments - `paused`: the subscription has been paused and will not create payments | | `upcoming_payments` | array | No | Up to 10 upcoming payments with their amounts and charge dates. | | `app_fee` | integer \| null | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `links` | object | No | | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `earliest_charge_date_after_resume` | string \| null | No | The earliest date that will be used as a `charge_date` on payments created for this subscription if it is resumed. Only present for `paused` subscriptions. This value will change over time. | | `parent_plan_paused` | boolean | No | Whether the parent plan of this subscription is paused. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Resume a subscription `POST /subscriptions/{subscription_id}/actions/resume` Resume a subscription object. Payments will start to be created again based on the subscriptions recurrence rules. The `charge_date` on the next payment will be the same as the subscriptions `earliest_charge_date_after_resume` This fails with: - `forbidden` if the subscription was created by an app and you are not authenticated as that app, or if the subscription was not created by an app and you are authenticated as an app - `validation_failed` if invalid data is provided when attempting to resume a subscription. - `subscription_not_paused` if the subscription is not paused.

Warning: There is a mandatory minimum 14 business day wait between resuming an `AUD` subscription and its next charge date. There is a mandatory minimum 10 calendar day wait between resuming an `NZD` subscription and its next charge date.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `subscription_id` | path | string | Yes | The subscription id | ### Request body Wrap request body attributes in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "SB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | No | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | integer \| null | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `currency` | string | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `count` | integer \| null | No | The total number of payments that should be taken by this subscription. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending_customer_approval`: the subscription is waiting for customer approval before becoming active - `customer_approval_denied`: the customer did not approve the subscription - `active`: the subscription is currently active and will continue to create payments - `finished`: all of the payments scheduled for creation under this subscription have been created - `cancelled`: the subscription has been cancelled and will no longer create payments - `paused`: the subscription has been paused and will not create payments | | `upcoming_payments` | array | No | Up to 10 upcoming payments with their amounts and charge dates. | | `app_fee` | integer \| null | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `links` | object | No | | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `earliest_charge_date_after_resume` | string \| null | No | The earliest date that will be used as a `charge_date` on payments created for this subscription if it is resumed. Only present for `paused` subscriptions. This value will change over time. | | `parent_plan_paused` | boolean | No | Whether the parent plan of this subscription is paused. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Cancel a subscription `POST /subscriptions/{subscription_id}/actions/cancel` Immediately cancels a subscription; no more payments will be created under it. Any metadata supplied to this endpoint will be stored on the payment cancellation event it causes. This will fail with a cancellation_failed error if the subscription is already cancelled or finished.

Warning: Please note that this will not cancel any payments that have already been created from this subscription — these payments will still be collected unless you also manually cancel them.

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `subscription_id` | path | string | Yes | The subscription id | ### Request body Wrap request body attributes in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `subscriptions` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "SB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `amount` | integer | No | Amount in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `name` | string \| null | No | Optional name for the subscription. This will be set as the description on each payment created. Must not exceed 255 characters. | | `start_date` | string \| null | No | The date on which the first payment should be charged. Must be on or after the [mandate](#core-endpoints-mandates)'s `next_possible_charge_date`. When left blank and `month` or `day_of_month` are provided, this will be set to the date of the first payment. If created without `month` or `day_of_month` this will be set as the mandate's `next_possible_charge_date` | | `end_date` | string \| null | No | Date on or after which no further payments should be created.
If this field is blank and `count` is not specified, the subscription will continue forever.

Deprecated: This field will be removed in a future API version. Use count to specify a number of payments instead.

| | `interval` | integer | No | Number of `interval_units` between customer charge dates. Must be greater than or equal to `1`. Must result in at least one charge date per year. Defaults to `1`. | | `interval_unit` | enum | No | The unit of time between customer charge dates. One of `weekly`, `monthly` or `yearly`. | | `day_of_month` | integer \| null | No | As per RFC 2445. The day of the month to charge customers on. `1`-`28` or `-1` to indicate the last day of the month. | | `currency` | string | No | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217#Active_codes) currency code. Currently "AUD", "CAD", "DKK", "EUR", "GBP", "NZD", "SEK" and "USD" are supported. | | `month` | enum \| null | No | Name of the month on which to charge a customer. Must be lowercase. Only applies when the interval_unit is `yearly`. | | `count` | integer \| null | No | The total number of payments that should be taken by this subscription. | | `payment_reference` | string \| null | No | An optional payment reference. This will be set as the reference on each payment created and will appear on your customer's bank statement. See the documentation for the [create payment endpoint](#payments-create-a-payment) for more details.

Restricted: You need your own Service User Number to specify a payment reference for Bacs payments.

| | `metadata` | object | No | Key-value store of custom data. Up to 3 keys are permitted, with key names up to 50 characters and values up to 500 characters. | | `status` | enum | No | One of: - `pending_customer_approval`: the subscription is waiting for customer approval before becoming active - `customer_approval_denied`: the customer did not approve the subscription - `active`: the subscription is currently active and will continue to create payments - `finished`: all of the payments scheduled for creation under this subscription have been created - `cancelled`: the subscription has been cancelled and will no longer create payments - `paused`: the subscription has been paused and will not create payments | | `upcoming_payments` | array | No | Up to 10 upcoming payments with their amounts and charge dates. | | `app_fee` | integer \| null | No | The amount to be deducted from each payment as an app fee, to be paid to the partner integration which created the subscription, in the lowest denomination for the currency (e.g. pence in GBP, cents in EUR). | | `links` | object | No | | | `retry_if_possible` | boolean | No | On failure, automatically retry payments using [intelligent retries](/success-plus/overview). Default is `false`.

Important: To be able to use intelligent retries, Success+ needs to be enabled in [GoCardless dashboard](https://manage.gocardless.com/success-plus).

| | `earliest_charge_date_after_resume` | string \| null | No | The earliest date that will be used as a `charge_date` on payments created for this subscription if it is resumed. Only present for `paused` subscriptions. This value will change over time. | | `parent_plan_paused` | boolean | No | Whether the parent plan of this subscription is paused. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## tax-rate URL: https://docs.gocardless.com/docs/api-reference/tax-rate # Tax Rate Source: https://docs.gocardless.com/docs/api-reference/tax-rate ## List tax rates `GET /tax_rates` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of all tax rates. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `jurisdiction` | query | string | No | The jurisdiction this tax rate applies to | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `tax_rates` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | The unique identifier created by the jurisdiction, tax type and version | | `jurisdiction` | string | Yes | The jurisdiction this tax rate applies to | | `type` | string | Yes | The type of tax applied by this rate | | `percentage` | string | Yes | The percentage of tax that is applied onto of GoCardless fees | | `start_date` | string | Yes | Date at which GoCardless started applying the tax rate in the jurisdiction. | | `end_date` | string \| null | Yes | Date at which GoCardless stopped applying the tax rate for the jurisdiction. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single tax rate `GET /tax_rates/{tax_rate_id}` Retrieves the details of a tax rate. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `tax_rate_id` | path | string | Yes | The tax rate id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `tax_rates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | Yes | The unique identifier created by the jurisdiction, tax type and version | | `jurisdiction` | string | Yes | The jurisdiction this tax rate applies to | | `type` | string | Yes | The type of tax applied by this rate | | `percentage` | string | Yes | The percentage of tax that is applied onto of GoCardless fees | | `start_date` | string | Yes | Date at which GoCardless started applying the tax rate in the jurisdiction. | | `end_date` | string \| null | Yes | Date at which GoCardless stopped applying the tax rate for the jurisdiction. | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## transferred-mandate URL: https://docs.gocardless.com/docs/api-reference/transferred-mandate # Transferred Mandate Source: https://docs.gocardless.com/docs/api-reference/transferred-mandate ## Get updated customer bank details `GET /transferred_mandates/{mandate_id}` Returns new customer bank details for a mandate that's been recently transferred

Restricted: This endpoint is restricted to organisations with the Transfer Bank Accounts upgrade

Note: See our [Security Requirements](#appendix-security-requirements) before using this feature

### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `mandate_id` | path | string | Yes | The mandate id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `transferred_mandates` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `encrypted_decryption_key` | string | No | Random AES-256 key used to encrypt bank account details, itself encrypted with your public key. | | `public_key_id` | string | No | The ID of an RSA-2048 public key, from your JWKS, used to encrypt the AES key. | | `encrypted_customer_bank_details` | string | No | Encrypted customer bank account details, containing: `iban`, `account_holder_name`, `swift_bank_code`, `swift_branch_code`, `swift_account_number` | | `links` | object | No | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## verification-detail URL: https://docs.gocardless.com/docs/api-reference/verification-detail # Verification Detail Source: https://docs.gocardless.com/docs/api-reference/verification-detail ## Create a verification detail `POST /verification_details` Creates a new verification detail

Warning: This endpoint only supports UK based limited companies. Therefore the creditor's `creditor_type` must be `'company'` and `country_code` must be `'GB'`.

### Request body Wrap request body attributes in a `verification_details` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | The company's legal name. | | `company_number` | string | Yes | The company's registration number. | | `description` | string | Yes | A summary describing what the company does. | | `address_line1` | string | Yes | The first line of the company's address. | | `address_line2` | string \| null | No | The second line of the company's address. | | `address_line3` | string \| null | No | The third line of the company's address. | | `city` | string | Yes | The city of the company's address. | | `postal_code` | string | Yes | The company's postal code. | | `directors` | array | Yes | The company's directors. | | `links` | object | Yes | | ### Responses | Status | Description | | --- | --- | | 201 | Resource created successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `verification_details` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | The company's legal name. | | `company_number` | string | Yes | The company's registration number. | | `description` | string | Yes | A summary describing what the company does. | | `address_line1` | string | Yes | The first line of the company's address. | | `address_line2` | string \| null | Yes | The second line of the company's address. | | `address_line3` | string \| null | Yes | The third line of the company's address. | | `city` | string | Yes | The city of the company's address. | | `postal_code` | string | Yes | The company's postal code. | | `region` | string \| null | Yes | The region of the company's address. | | `country_code` | string | Yes | The country code of the company's address. | | `directors` | array | Yes | The company's directors. | | `links` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## List verification details `GET /verification_details` Returns a list of verification details belonging to a creditor. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `creditor` | query | string | Yes | Unique identifier, beginning with "CR". | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `verification_details` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `name` | string | Yes | The company's legal name. | | `company_number` | string | Yes | The company's registration number. | | `description` | string | Yes | A summary describing what the company does. | | `address_line1` | string | Yes | The first line of the company's address. | | `address_line2` | string \| null | Yes | The second line of the company's address. | | `address_line3` | string \| null | Yes | The third line of the company's address. | | `city` | string | Yes | The city of the company's address. | | `postal_code` | string | Yes | The company's postal code. | | `region` | string \| null | Yes | The region of the company's address. | | `country_code` | string | Yes | The country code of the company's address. | | `directors` | array | Yes | The company's directors. | | `links` | object | Yes | | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | ## webhook URL: https://docs.gocardless.com/docs/api-reference/webhook # Webhook Source: https://docs.gocardless.com/docs/api-reference/webhook ## List webhooks `GET /webhooks` Returns a [cursor-paginated](#api-usage-cursor-pagination) list of your webhooks. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `before` | query | string \| null | No | Cursor pointing to the end of the desired set. | | `after` | query | string \| null | No | Cursor pointing to the start of the desired set. | | `limit` | query | | No | Number of records to return. | | `created_at` | query | object | No | | | `successful` | query | | No | Show only successful/failed webhooks | | `is_test` | query | | No | Show only test/non test webhooks | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body Each item in the `webhooks` array has the following attributes. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "WB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `url` | string | No | URL the webhook was POST-ed to | | `request_headers` | object | No | The request headers sent with the webhook | | `request_body` | string | No | The body of the request sent to the webhook URL | | `response_code` | integer \| null | No | The response code from the webhook request | | `response_body` | string \| null | No | The body of the response from the webhook URL | | `response_body_truncated` | boolean \| null | No | Boolean value indicating the webhook response body was truncated | | `response_headers` | object \| null | No | The headers sent with the response from the webhook URL | | `response_headers_content_truncated` | boolean \| null | No | Boolean indicating the content of response headers was truncated | | `response_headers_count_truncated` | boolean \| null | No | Boolean indicating the number of response headers was truncated | | `is_test` | boolean | No | Boolean value showing whether this was a demo webhook for testing | | `successful` | boolean | No | Boolean indicating whether the request was successful or failed | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Get a single webhook `GET /webhooks/{webhook_id}` Retrieves the details of an existing webhook. ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `webhook_id` | path | string | Yes | The webhook id | ### Responses | Status | Description | | --- | --- | | 200 | Successful response | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `webhooks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "WB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `url` | string | No | URL the webhook was POST-ed to | | `request_headers` | object | No | The request headers sent with the webhook | | `request_body` | string | No | The body of the request sent to the webhook URL | | `response_code` | integer \| null | No | The response code from the webhook request | | `response_body` | string \| null | No | The body of the response from the webhook URL | | `response_body_truncated` | boolean \| null | No | Boolean value indicating the webhook response body was truncated | | `response_headers` | object \| null | No | The headers sent with the response from the webhook URL | | `response_headers_content_truncated` | boolean \| null | No | Boolean indicating the content of response headers was truncated | | `response_headers_count_truncated` | boolean \| null | No | Boolean indicating the number of response headers was truncated | | `is_test` | boolean | No | Boolean value showing whether this was a demo webhook for testing | | `successful` | boolean | No | Boolean indicating whether the request was successful or failed | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | | --- ## Retry a webhook `POST /webhooks/{webhook_id}/actions/retry` Requests for a previous webhook to be sent again ### Parameters | Name | Location | Type | Required | Description | | --- | --- | --- | --- | --- | | `webhook_id` | path | string | Yes | The webhook id | ### Responses | Status | Description | | --- | --- | | 200 | Action completed successfully | | 400 | Bad Request | | 401 | Unauthorised | | 404 | Not found | | 422 | Validation Error | | 500 | Internal Error | ### Response body The response is wrapped in a `webhooks` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `id` | string | No | Unique identifier, beginning with "WB". | | `created_at` | string | No | Fixed [timestamp](#api-usage-dates-and-times), recording when this resource was created. | | `url` | string | No | URL the webhook was POST-ed to | | `request_headers` | object | No | The request headers sent with the webhook | | `request_body` | string | No | The body of the request sent to the webhook URL | | `response_code` | integer \| null | No | The response code from the webhook request | | `response_body` | string \| null | No | The body of the response from the webhook URL | | `response_body_truncated` | boolean \| null | No | Boolean value indicating the webhook response body was truncated | | `response_headers` | object \| null | No | The headers sent with the response from the webhook URL | | `response_headers_content_truncated` | boolean \| null | No | Boolean indicating the content of response headers was truncated | | `response_headers_count_truncated` | boolean \| null | No | Boolean indicating the number of response headers was truncated | | `is_test` | boolean | No | Boolean value showing whether this was a demo webhook for testing | | `successful` | boolean | No | Boolean indicating whether the request was successful or failed | ### Error body Errors are wrapped in an `error` object. | Field | Type | Required | Description | | --- | --- | --- | --- | | `code` | integer | No | | | `documentation_url` | string | No | | | `errors` | array | Yes | | | `message` | string | Yes | | | `request_id` | string | Yes | | | `type` | string | No | |