Variable Recurring Payments
Billing Request actions
In order to access the following endpoints and complete the required actions integrators will need the custom payment pages upgrade enabled on their account.
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 currenciescollect_customer_details
: collect customer details required for the schemesselect_institution
: collect customer bank institutioncollect_bank_account
: create the bank account for the mandate/paymentbank_authorisation
: have the payer authorise the billing request via their bank if requiredconfirm_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 action to create all associated resources.
Which actions should I implement?
Even if integrators complete a selection of actions themselves, Billing Request Flows can be used to complete the remaining actions.
Our recommendations for whether integrators should implement each action are:
choose_currency
: implement this if you want to allow the payer to have the ability to choose a different currency, and you support more than 1 currency.collect_customer_details
: implement this if you want a white label flow to collect customer details or have already collected the details (pre-filling, etc)select_institution
: implement this to allow the payer to select their bank institution, this is required before a bank authorisation can be created.collect_bank_account
: as with customer details, but be aware that Billing Request Flows can avoid this step for certain schemes which can improve conversion by reducing the number of details a payer has to manually input.confirm_payer_details
: as part of scheme compliance, it is a requirement to allow the payer to crosscheck the details entered by them and confirm them.bank_authorisation
: can be handled via the Billing Request Flow, but if the custom payment pages - bank authorisation upgrade is enabled on your account, thebank_authorisation
endpoint can be used.
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 a bank_authorisation
as an example:
1{
2 "type": "bank_authorisation",
3 "status": "completed",
4 "required": true,
5 "completes_actions": [
6 "collect_customer_details"
7 ],
8 "requires_actions": [
9 "collect_bank_account"
10 ]
11}
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 the bank authorisation until we’ve collected the bank.
completes_actions:
Actions can complete other actions, which can help streamline checkout flows. The example shows how a bank authorisation might collect customer details, completing that action as a side effect.
For most integrators, we suggest building flows that process actions in the order of:
choose_currency
,collect_customer_details
, so customer contact details are prioritisedcollect_bank_account
, if it is required and another action won’t complete itselect_institution,
if it is required and another action won’t complete itbank_authorisation
, as the penultimate step before completing the checkout flowconfirm_payer_details
, only applicable if it is amandate_request
The hosted checkout flow provided by Billing Request Flows is built to optimise conversion, and will follow the minimum number of steps to fulfil the Billing Request. Most integrators should lean on the flow to complete anything beyond collection of customer details.
Action: collect_customer_details
Billing Requests aim to create billing resources against a customer, either a mandate (Direct Debit, PayTo or VRPs), an Instant Bank Payment, 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 create a Billing Request for a GBP mandate:
1POST /billing_requests
2{
3 "billing_requests": {
4 "mandate_request": {
5 "currency": "GBP"
6 }
7 }
8}
This returns a Billing Request that looks like this:
1{
2 "billing_requests": {
3 "id": "BRQ000010NMDMH2",
4 "status": "pending",
5 "mandate_request": {
6 "scheme": "bacs",
7 "currency": "GBP"
8 },
9 "links": {
10 "customer": "CU00016WDAM7BS",
11 "customer_billing_detail": "CBD000010P52VRF",
12 "organisation": "OR123"
13 },
14 "actions": [
15 {
16 "type": "collect_customer_details",
17 "required": true,
18 "completes_actions": [],
19 "requires_actions": [
20 "choose_currency"
21 ],
22 "status": "pending",
23 "collect_customer_details": {
24 "incomplete_fields": {
25 "customer": [
26 "email",
27 "given_name",
28 "family_name"
29 ],
30 "customer_billing_detail": [
31 "address_line1",
32 "city",
33 "postal_code",
34 "country_code"
35 ]
36 }
37 }
38 },
39 ...,
40 ],
41 "resources": {
42 "customer": {
43 "id": "CU00016WDAM7BS",
44 "created_at": "2021-04-08T14:06:30.977Z",
45 "email": null,
46 "given_name": null,
47 "family_name": null,
48 "company_name": null,
49 "language": "en",
50 "phone_number": null,
51 "metadata": {}
52 },
53 "customer_billing_detail": {
54 "id": "CBD000010P52VRF",
55 "created_at": "2021-04-08T14:06:30.997Z",
56 "address_line1": null,
57 "address_line2": null,
58 "address_line3": null,
59 "city": null,
60 "region": null,
61 "postal_code": null,
62 "country_code": null,
63 "swedish_identity_number": null,
64 "danish_identity_number": null
65 }
66 }
67 }
68}
Note that:
There is a
collect_customer_details
action, which ispending
A new customer has been created for us, as the Billing Request wasn’t attached to an existing customer
The
customer
andcustomer_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:
1{
2 "type": "collect_customer_details",
3 "required": true,
4 "completes_actions": [],
5 "requires_actions": [
6 "choose_currency"
7 ],
8 "status": "pending",
9 "collect_customer_details": {
10 "incomplete_fields": {
11 "customer": [
12 "email",
13 "given_name",
14 "family_name"
15 ],
16 "customer_billing_detail": [
17 "address_line1",
18 "city",
19 "postal_code",
20 "country_code"
21 ]
22 }
23 }
24}
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 endpoint:
1$client = new \GoCardlessPro\Client(array(
2 'access_token' => 'your_access_token_here',
3 'environment' => \GoCardlessPro\Environment::SANDBOX
4));
5
6$client->billingRequests()->collectCustomerDetails("BR123", [
7 "params" => [
8 "customer" => [
9 "given_name" => "Alice",
10 "family_name" => "Smith"
11 ],
12 "customer_billing_detail" => [
13 "address_line1" => "1 Somewhere Lane"
14 ]
15 ]
16]);
As with all action endpoints, the response is the Billing Request. What we get back is:
1{
2 "billing_requests": {
3 "id": "BRQ000010NMDMH2",
4 "status": "pending",
5 "mandate_request": {
6 "scheme": "bacs",
7 "currency": "GBP",
8 },
9 "links": {
10 "customer": "CU00016WDAM7BS",
11 "customer_billing_detail": "CBD000010P52VRF",
12 "organisation": "OR123"
13 },
14 "actions": [
15 {
16 "type": "collect_customer_details",
17 "required": true,
18 "completes_actions": [],
19 "requires_actions": [
20 "choose_currency"
21 ],
22 "status": "completed",
23 "collect_customer_details": {
24 "incomplete_fields": {
25 "customer": [],
26 "customer_billing_detail": []
27 }
28 }
29 },
30 ...,
31 ],
32 "resources": {
33 "customer": {
34 "id": "CU00016WDAM7BS",
35 "created_at": "2021-04-08T14:06:30.977Z",
36 "email": "paddington@bearthings.com",
37 "given_name": "Paddington",
38 "family_name": "Bear",
39 "company_name": null,
40 "language": "en",
41 "phone_number": null,
42 "metadata": {}
43 },
44 "customer_billing_detail": {
45 "id": "CBD000010P52VRF",
46 "created_at": "2021-04-08T14:06:30.997Z",
47 "address_line1": "32 Windsor Gardens",
48 "address_line2": null,
49 "address_line3": null,
50 "city": "London",
51 "region": null,
52 "postal_code": "W9 3RG",
53 "country_code": "GB",
54 "swedish_identity_number": null,
55 "danish_identity_number": null
56 }
57 }
58 }
59}
Note that:
The
collect_customer_details
action is nowcompleted
, meaning we can move on to other actionsAs a result of us collecting the details, our
customer
andcustomer_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 schema) but only display the inputs required, as per incomplete_fields
.
Depending on the scheme, we might need to collect bank account details before fulfilling the Billing Request. An example is a VRPs mandate, where we need to capture the payer’s bank in order to create payments against them.
As an example, we have a Billing Request which requires collect_bank_account
:
1{
2 "billing_requests": {
3 "id": "BRQ000010NMDMH2",
4 "status": "pending",
5 ...,
6 "links": {
7 "customer": "CU00016WDAM7BS",
8 "customer_billing_detail": "CBD000010PAJ810",
9 "organisation": "OR123"
10 },
11 "actions": [
12 {
13 "type": "collect_bank_account",
14 "required": true,
15 "completes_actions": [
16 "choose_currency"
17 ],
18 "requires_actions": [],
19 "status": "pending"
20 },
21 ...,
22 ],
23 }
24}
Note that:
There is a
collect_bank_account
action that ispending
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 endpoint:
1$client = new \GoCardlessPro\Client(array(
2 'access_token' => 'your_access_token_here',
3 'environment' => \GoCardlessPro\Environment::SANDBOX
4));
5
6$client->billingRequests()->collectBankAccount("BRQ000010NMDMH2", [
7 "params" => [
8 "account_number" => "55779911",
9 "branch_code" => "200000",
10 "account_holder_name" => "Frank Osborne",
11 "country_code" => "GB"
12 ]
13]);
As with all action endpoints, the response is the Billing Request. What we get back is:
1{
2 "billing_requests": {
3 "id": "BRQ000010NMDMH2",
4 "status": "ready_to_fulfil",
5 "mandate_request": {
6 "currency": "GBP"
7 },
8 "links": {
9 "customer": "CU00016WDAM7BS",
10 "customer_billing_detail": "CBD000010P52VRF",
11 "customer_bank_account": "BA0000QDWEEAFB",
12 "organisation": "OR123"
13 },
14 "actions": [
15 {
16 "type": "collect_bank_account",
17 "required": true,
18 "completes_actions": [
19 "choose_currency"
20 ],
21 "requires_actions": [],
22 "status": "completed"
23 },
24 ...,
25 ],
26 "resources": {
27 "customer_bank_account": {
28 "id": "BA0000QDWEEAFB",
29 "created_at": "2021-04-08T15:30:36.019Z",
30 "account_number_ending": "51",
31 "account_holder_name": "PADDINGTON BEAR",
32 "account_type": null,
33 "bank_name": "MONZO BANK LIMITED",
34 "currency": "GBP",
35 "country_code": "GB",
36 "metadata": {},
37 "enabled": true,
38 "links": {
39 "customer": "CU00016WDAM7BS"
40 }
41 }
42 }
43 }
44}
Note that:
The
collect_bank_account
action is nowcompleted
, meaning we can move on to other actionsAs a result of us collecting the bank account, we have created a
customer_bank_account
resource and you can see thelinks.customer_bank_account
ID has been set
We advise most integrators use Billing Request Flows to complete this action, as the hosted flows will try skipping this action if it can be fulfilled by another (such as bank authorisation).
Select Institution auto-completion
In cases where GoCardless is able to guess the institution for the bank details provided, we will auto-complete the following action select_institution
. When we are unable to guess the response for the Billing Request will leave the status of select_institution
as "pending"
The select institution action ensures an institution resource is attached to the Billing Request. An institution is required to create a bank authorisation (next step). If GoCardless is able to guess the customer's institution from their bank account this will make this step optional.
Integrators should present a list of institutions to the payer, which they can populate from the List Institutions for Billing Request endpoint:
1$client = new \GoCardlessPro\Client(array(
2 'access_token' => 'your_access_token_here',
3 'environment' => \GoCardlessPro\Environment::SANDBOX
4));
5
6$client->institutions()->list_for_billing_request("BR123", [
7 "params" => ["country_code" => "GB"]
8]);
Which responds with the institutions that GoCardless supports for bank authorisation:
1{
2 "institutions": [
3 {
4 "id": "monzo",
5 "name": "Monzo",
6 "logo_url": "https://assets.gocardless.com/icon",
7 "icon_url": "https://assets.gocardless.com/icon",
8 "country_code": "GB"
9 }
10 ]
11}
Call Select Institutions for Billing Request endpoint once the payer has selected their institution.
1$client = new \GoCardlessPro\Client(array(
2 'access_token' => 'your_access_token_here',
3 'environment' => \GoCardlessPro\Environment::SANDBOX
4));
5
6$client->billingRequests()->selectInstitution("BR123", [
7 "params" => ["country_code" => "GB", "institution" => "monzo"]
8]);
As with all action endpoints, the response is the Billing Request. What we get back is:
1{
2 "billing_requests": {
3 "id": "BRQ123",
4 "status": "pending",
5 ...,
6 "links": {
7 "customer": "CU123",
8 "customer_billing_detail": "CBD123",
9 "customer_bank_account": "BA123",
10 "organisation": "OR123"
11 },
12 "actions": [
13 {
14 "type": "select_institution",
15 "required": true,
16 "completes_actions": [],
17 "requires_actions": [],
18 "status": "completed"
19 },
20 ...,
21 ],
22 "resources": {
23 "institution": {
24 "id": "monzo",
25 "name": "Monzo",
26 "logo_url": "https://assets.gocardless.com/icon",
27 "icon_url": "https://assets.gocardless.com/icon",
28 "country_code": "GB",
29 }
30 }
31 }
32}
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 can create a Billing Request for a GBP mandate:
1POST /billing_requests
2{
3 "billing_requests": {
4 "mandate_request": {
5 "currency": "GBP"
6 }
7 }
8}
This returns a Billing Request that looks like this:
1{
2 "billing_requests": {
3 "id": "BRQ000010NMDMH2",
4 "status": "pending",
5 "mandate_request": {
6 "currency": "GBP",
7 },
8 "links": {
9 "customer": "CU00016WDAM7BS",
10 "customer_billing_detail": "CBD000010PAJ810",
11 "organisation": "OR123"
12 },
13 "actions": [
14 {
15 "type": "confirm_payer_details",
16 "required": true,
17 "completes_actions": [],
18 "requires_actions": [
19 "collect_customer_details",
20 "collect_bank_account"
21 ],
22 "status": "pending"
23 }
24 ...,
25 ],
26 }
27}
Note that:
There is a
confirm_payer_details
action that ispending
The action is
required
- all mandate requests will require thisThe action requires
collect_customer_details
andcollect_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 endpoint:
1$client = new \GoCardlessPro\Client(array(
2 'access_token' => 'your_access_token_here',
3 'environment' => \GoCardlessPro\Environment::SANDBOX
4));
5
6$client->billingRequests()->confirmPayerDetails("BR123");
As with all action endpoints, the response is the Billing Request. What we get back is:
1{
2 "billing_requests": {
3 "id": "BRQ000010NMDMH2",
4 "status": "ready_to_fulfil",
5 "mandate_request": {
6 "currency": "GBP"
7 },
8 "links": {
9 "customer": "CU00016WDAM7BS",
10 "customer_billing_detail": "CBD000010P52VRF",
11 "customer_bank_account": "BA0000QDWEEAFB",
12 "organisation": "OR123"
13 },
14 "actions": [
15 {
16 "type": "confirm_payer_details",
17 "required": true,
18 "completes_actions": [],
19 "requires_actions": [
20 "collect_customer_details",
21 "collect_bank_account"
22 ],
23 "status": "completed"
24 },
25 ...,
26 ],
27 "resources": {
28 ...,
29 }
30 }
31 }
32}
Note that:
The
confirm_payer_details
action is nowcompleted
, and the billing request will change status toready_to_fulfil
.This Billing Request can now be fulfilled by POST'ing to the Fulfil a Billing Request Endpoint
We advise most integrators to use Billing Request Flows to complete this action, as information presented in the confirmation screen changes depending on the scheme.
Custom Payment Pages - Bank Authorisation requires compliance component
To continue creating a Bank Authorisation in your Custom Payment Pages, you must first render the compliance component to the payer. This will display to the user the payer terms and that the payment or mandate is powered by GoCardless.
Please see instructions on how to use this here: Custom Payment Pages - Compliance Component
One of the most complex actions, bank_authorisation
means the payer needs to log in to their bank to authorise the Billing Request. All Open Banking schemes will require this action, while bank debit requests may offer an optional bank_authorisation
(coming soon!).
If an integrator has white-labelled the other actions, they should create a Billing Request Flow to handle the bank_authorisation
, as we have invested significant time to optimise the flow.
As an example, the Billing Request response will have a required action for bank_authorisation
:
1{
2 "billing_requests": {
3 "id": "BRQ000010NVSP5H",
4 "status": "pending",
5 ...,
6 "actions": [
7 {
8 "type": "bank_authorisation",
9 "required": true,
10 "completes_actions": [],
11 "requires_actions": [
12 "collect_bank_account",
13 "select_institution"
14 ],
15 "status": "pending"
16 },
17 ...,
18 ]
19 }
20}
Note that:
There is a
bank_authorisation
action which ispending
The action is
required
- all requests for IBP & VRPs will require bank authorisationThe action requires
collect_bank_account
andselect_institution
, as we can only authorise the payment after we have collected both the institution and the bank details.
Once all dependent required actions are completed, we can generate an authorisation using the Create a Bank Authorisation endpoint:
1$client = new \GoCardlessPro\Client(array(
2 'access_token' => 'your_access_token_here',
3 'environment' => \GoCardlessPro\Environment::SANDBOX
4));
5
6$client->bankAuthorisations()->create([
7 "params" => [
8 "redirect_uri" => "https://my-company.com/landing",
9 "links" => [
10 "billing_request" => "BRQ123"
11 ]
12 ]
13]);
This request will contact the payers bank directly. It is worth noting that banks have varying reliability for open-banking requests, and this request may fail due to the retail bank being unavailable.
If successful, we’ll respond with:
1{
2 "bank_authorisations": {
3 "id": "BAU123",
4 "url": "https://pay-staging.gocardless.com/obauth/BAU123",
5 "qr_code_url": "https://pay-staging.gocardless.com/obauth/BAU123/qr_code",
6 "authorisation_type": "payment",
7 "last_visited_at": null,
8 "expires_at": "2021-03-25T17:41:28.000Z",
9 "redirect_uri": "https://my-company.com/landing",
10 "links": {
11 "institution": "monzo",
12 "billing_request": "BRQ000010NVSP5H"
13 }
14 }
15}
Payers will be redirected to the url
in this response, which will open the payer’s bank login screen. If opened on a mobile with the retail bank app installed, it’s possible the payer will jump straight into the app to authorise the payment.
Alternatively, you can provide the QR code image provided in the qr_code_url
in your application to allow payers to go seamlessly from desktop to their mobile banking app like this: <img src="
https://pay-staging.gocardless.com/obauth/BAU123/qr_code
">
The bank authorisation is queryable, and will be updated once the payer authorises/denies the request. Integrators should have their checkout flows poll the Get a Bank Authorisation endpoint until the authorised_at
timestamp is set.
Once the authorisation is complete, the Billing Request will update to mark the action as completed:
1{
2 "billing_requests": {
3 "id": "BRQ000010NVSP5H",
4 "status": "ready_to_fulfil",
5 "payment_request": {
6 "description": "Large pot of Marmalade",
7 "currency": "GBP",
8 "amount": 10,
9 "scheme": "faster_payments",
10 },
11 "actions": [
12 {
13 "type": "bank_authorisation",
14 "required": true,
15 "completes_actions": [],
16 "requires_actions": [
17 "collect_bank_account",
18 "select_institution"
19 ],
20 "status": "completed"
21 },
22 ...,
23 ]
24 }
25}
Preventing Breaking changes
In order to automatically receive new features and always remain scheme compliant without having to change your integration, GoCardless will need to adjust actions by adding new actions or making optional actions required. This means it will break your integration if you don’t fall back to Billing Request Flow. Therefore if you are building custom payment pages you needs to Implement the actions you are aware of and want to process.
If you reach the last action and the Billing Request is still pending
(as opposed to ready_to_fulfil
or fulfilled
), then you need to create a Billing Request Flow and send the payers through that flow.
What’s next?
Responding to Billing Requests events
Get started
First instant payment with mandate Direct Debit set up
For partners
Go to Partner PortalTo learn more about technical and UX requirements