# Billing Request (Instant Bank Pay feature)

## 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.

### What are Billing Request Actions?

### 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
- `bank_authorisation`, have the payer authorise the billing request via their bank if required
- `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](https://developer.gocardless.com/api-reference/#billing-requests-fulfil-a-billing-request) 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)
- `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 it.
- `bank_authorisation`, this can be handled by Billing Request Flows or in Instant Bank Pay via a custom Bank Authorisation creation.

### 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 a `bank_authorisation` as an example:

```json
{
  "type": "bank_authorisation",
  "status": "completed",
  "required": true,
  "completes_actions": ["collect_customer_details"],
  "requires_actions": ["collect_bank_account"]
}
```

**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:

1. `choose_currency`,` `optional first step as a change in scheme can dictate what customer contact details we collect
2. `collect_customer_details`, so customer contact details are prioritised
3. `collect_bank_account`, if it is required and another action won’t complete it
4. `bank_authorisation`, as the penultimate step before completing the checkout flow
5. `confirm_payer_details`, only applicable if it is a `mandate_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: choose_currency

### Action: `choose_currency`

Depending on your preference, and if you support multiple currencies you can allow the customer to change their currency to their preferred option for mandate only requests.

As an example, we can create a Billing Request for a GBP mandate:

```http
POST /billing_requests
{
  "billing_requests": {
    "mandate_request": {
       "currency": "GBP"
    }
  }
}
```

This returns a Billing Request that looks like this:

```json
{
  "billing_requests": {
    "id": "BRQ000010NMDMH2",
    "status": "pending",
    "mandate_request": {
       "scheme": "bacs",
      "currency": "GBP"
    },
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010P52VRF",
      "organisation": "OR123"
    },
    "actions": [
      {
        "type": "choose_currency",
        "required": true,
        "completes_actions": [],
        "requires_actions": [],
        "status": "completed",
        "available_currencies": ["USD", "GBP", "EUR"]
      },
      ...,
    ],
   ...,
  }
}
```

Note that

- There is a `choose_currency `action, which is `completed - `this is because we have supplied a currency when created the BR, however we still have the ability to change it.
- There is an `available_currencies `field` `which has a list of currencies the payer will be able to choose from.

We can complete this action by POST’ing to the [Choose Currency for the billing request](/api-reference/#billing-requests-change-currency) endpoint:

```php
$client = new \GoCardlessPro\Client(array(
  'access_token' => 'your_access_token_here',
  'environment'  => \GoCardlessPro\Environment::SANDBOX
));

$client->billingRequests()-> chooseCurrency("BRQ000010NMDMH2", [
  "params" => [
    "currency" => "USD"
  ]
]);
```

```python
import gocardless_pro
client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox')

client.billing_requests.choose_currency("BRQ000010NMDMH2", params={
  currency: "USD"
})
```

```ruby
@client = GoCardlessPro::Client.new(
  access_token: "your_access_token",
  environment: :sandbox
)

@client.billing_requests.choose_currency("BRQ000010NMDMH2", {
  params: {
    currency: "USD"
  }
})
```

```java
import static com.gocardless.GoCardlessClient.Environment.SANDBOX;
String accessToken = "your_access_token_here";
GoCardlessClient client = GoCardlessClient
    .newBuilder(accessToken)
    .withEnvironment(SANDBOX)
    .build();

client.billingRequests().chooseCurrency("BRQ000010NMDMH2")
  .withCurrency("USD")
  .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.chooseCurrency("BRQ000010NMDMH2", {
  currency: "USD",
});
```

```.net
String accessToken = "your_access_token";
GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX);

var resp = await gocardless.BillingRequests.ChooseCurrency("BRQ000010NMDMH2",
  new BillingRequestChooseCurrencyRequest
  {
    Currency = "USD"
  });
```

```HTTP
POST /billing_requests/BRQ000010NMDMH2/actions/choose_currency HTTP/1.1
{
  "data": {
     "currency": "USD"
  }
}
```

```go
package main

import (
	gocardless "github.com/gocardless/gocardless-pro-go/v2"
)

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
}

BillingRequestChooseCurrencyParams := gocardless.BillingRequestChooseCurrencyParams{
  Currency: "USD",
}

billingRequest, err := client.BillingRequests.ChooseCurrency(context, "BRQ000010NMDMH2", BillingRequestChooseCurrencyParams)
```

As with all action endpoints, the response is the Billing Request. What we get back is:

```json
{
  "billing_requests": {
    "id": "BRQ000010NMDMH2",
    "status": "pending",
    "mandate_request": {
        "currency": "USD"
        "scheme": "ach"
    },
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010P52VRF",
      "organisation": "OR123"
    },
    "actions": [
      {
        "type": "choose_currency",
        "required": true,
        "completes_actions": [],
        "requires_actions": [],
        "status": "completed",
        "available_currencies": ["USD", "GBP", "EUR"]
      },
   ...,
  }
}
```

Note that:

- Our Mandate request now has an updated currency and scheme.

### Action: collect_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:

```http
POST /billing_requests
{
  "billing_requests": {
    "mandate_request": {
       "currency": "GBP"
    }
  }
}
```

This returns a Billing Request that looks like this:

```json
{
  "billing_requests": {
    "id": "BRQ000010NMDMH2",
    "status": "pending",
    "mandate_request": {
      "scheme": "bacs",
      "currency": "GBP"
    },
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010P52VRF",
      "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"
            ]
          }
        }
      },
      ...,
    ],
    "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": "CBD000010P52VRF",
        "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"
      ]
    }
  }
}
```

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](https://developer.gocardless.com/api-reference/#billing-requests-collect-customer-details) endpoint:

```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
import gocardless_pro
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"
  }
});
```

```.net
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

import (
	gocardless "github.com/gocardless/gocardless-pro-go/v2"
)

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)
```

As with all action endpoints, the response is the Billing Request. What we get back is:

```json
{
  "billing_requests": {
    "id": "BRQ000010NMDMH2",
    "status": "pending",
    "mandate_request": {
      "scheme": "bacs",
      "currency": "GBP",
    },
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010P52VRF",
      "organisation": "OR123"
    },
    "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": "paddington@bearthings.com",
        "given_name": "Paddington",
        "family_name": "Bear",
        "company_name": null,
        "language": "en",
        "phone_number": null,
        "metadata": {}
      },
      "customer_billing_detail": {
        "id": "CBD000010P52VRF",
        "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 `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](https://developer.gocardless.com/api-reference/#billing-requests-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 have a Billing Request which requires `collect_bank_account`:

```json
{
  "billing_requests": {
    "id": "BRQ000010NMDMH2",
    "status": "pending",
    ...,
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010PAJ810",
      "organisation": "OR123"
    },
    "actions": [
      {
        "type": "collect_bank_account",
        "required": true,
        "completes_actions": [
          "choose_currency"
        ],
        "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](https://developer.gocardless.com/api-reference/#billing-requests-collect-bank-account-details) endpoint:

```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
import gocardless_pro
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
import static com.gocardless.GoCardlessClient.Environment.SANDBOX;
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",
  },
);
```

```.net
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

import (
	gocardless "github.com/gocardless/gocardless-pro-go/v2"
)

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)
```

As with all action endpoints, the response is the Billing Request. What we get back is:

```json
{
  "billing_requests": {
    "id": "BRQ000010NMDMH2",
    "status": "ready_to_fulfil",
    "mandate_request": {
      "currency": "GBP"
    },
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010P52VRF",
      "customer_bank_account": "BA0000QDWEEAFB",
      "organisation": "OR123"
    },
    "actions": [
      {
        "type": "collect_bank_account",
        "required": true,
        "completes_actions": [
          "choose_currency"
        ],
        "requires_actions": [],
        "status": "completed"
      },
      ...,
    ],
    "resources": {
      "customer_bank_account": {
        "id": "BA0000QDWEEAFB",
        "created_at": "2021-04-08T15:30:36.019Z",
        "account_number_ending": "51",
        "account_holder_name": "PADDINGTON BEAR",
        "account_type": null,
        "bank_name": "MONZO BANK LIMITED",
        "currency": "GBP",
        "country_code": "GB",
        "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

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).

### Action: bank_authorisation

One of the most complex actions, `bank_authorisation` means the payer needs to log in to their bank to authorise the Billing Request. All Instant Bank Pay schemes will require this action, while mandate only requests will offer an optional `bank_authorisation`.

> The creation of `bank_authorisation` is only permitted from GoCardless hosted UIs to ensure we meet regulatory requirements. This action can be completed by creating a [Billing Request Flow](https://developer.gocardless.com/api-reference/#billing-request-flows-create-a-billing-request-flow) and redirecting the payers through the `authorisation_url` provided. Once the payer is redirected, the Billing Request Flow will ensure all the other pending actions are completed and the Billing Request is fulfilled .

The previous actions may return a bank authorisation in pending state:

```json
{
  "billing_requests": {
    "id": "BRQ000010NVSP5H",
    "status": "pending",
    "mandate_request": {
      "currency": "GBP",
      "scheme": "bacs",
    },
    "actions": [
      {
        "type": "bank_authorisation",
        "required": true,
        "completes_actions": [],
        "requires_actions": [
          "collect_bank_account"
        ],
        "status": "pending"
      },
      ...,
    ]
  }
}
```

Note that:

- There is a `bank_authorisation` action which is pending
- The action is required - all requests with Instant Bank Payments will require bank authorisation
- The action requires `collect_bank_account`, as we can only authorise the payment after we have collected bank.

We need to create a Billing Request Flow with the ID of Billing Request we had created earlier in order to proceed with the bank 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
import gocardless_pro
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
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()
  .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",
  },
});
```

```.net
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

import (
	gocardless "github.com/gocardless/gocardless-pro-go"
)

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=<brf_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"
    }
  }
}
```

Share your **authorisation  **from the response above via a button on your website, SMS, email, or any other way you like. Payers can then follow the authorisation link 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.

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**](https://developer.gocardless.com/api-reference/#bank-authorisations-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:

```json
{
  "billing_requests": {
    "id": "BRQ000010NVSP5H",
    "status": "ready_to_fulfil",
    "payment_request": {
      "description": "Large pot of Marmalade",
      "currency": "GBP",
      "amount": 10,
      "scheme": "faster_payments",
    },
    "actions": [
      {
        "type": "bank_authorisation",
        "required": true,
        "completes_actions": [],
        "requires_actions": [
          "collect_bank_account",
          "select_institution"
        ],
        "status": "completed"
      },
      ...,
    ]
  }
}
```

### 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 can create a Billing Request for a GBP mandate:

```http
POST /billing_requests
{
  "billing_requests": {
    "mandate_request": {
       "currency": "GBP"
    }
  }
}
```

This returns a Billing Request that looks like this:

```json
{
  "billing_requests": {
    "id": "BRQ000010NMDMH2",
    "status": "pending",
    "mandate_request": {
      "currency": "GBP",
    },
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010PAJ810",
      "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](https://developer.gocardless.com/api-reference/#billing-requests-confirm-the-payer-details) endpoint:

```PHP
$client = new \GoCardlessPro\Client(array(
  'access_token' => 'your_access_token_here',
  'environment'  => \GoCardlessPro\Environment::SANDBOX
));

$client->billingRequests()->confirmPayerDetails("BR123");
```

```python
import gocardless_pro
client = gocardless_pro.Client(access_token="your_access_token_here", environment='sandbox')

client.billing_requests.confirm_payer_details("BR123")
```

```ruby
@client = GoCardlessPro::Client.new(
  access_token: "your_access_token",
  environment: :sandbox
)

@client.billing_requests.confirm_payer_details("BR123")
```

```java
import static com.gocardless.GoCardlessClient.Environment.SANDBOX;
String accessToken = "your_access_token_here";
GoCardlessClient client = GoCardlessClient
    .newBuilder(accessToken)
    .withEnvironment(SANDBOX)
    .build();

client.billingRequests().confirmPayerDetails("BR123").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.confirmPayerDetails("BR123");
```

```.net
String accessToken = "your_access_token";
GoCardlessClient gocardless = GoCardlessClient.Create(accessToken, Environment.SANDBOX);

var resp = await gocardless.BillingRequests.ConfirmPayerDetailsAsync("BR123");
```

```HTTP
POST https://api.gocardless.com/billing_requests/BRQ123/actions/confirm_payer_details HTTP/1.1
```

```go
package main

import (
	gocardless "github.com/gocardless/gocardless-pro-go/v2"
)

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": "BRQ000010NMDMH2",
    "status": "ready_to_fulfil",
    "mandate_request": {
      "currency": "GBP"
    },
    "links": {
      "customer": "CU00016WDAM7BS",
      "customer_billing_detail": "CBD000010P52VRF",
      "customer_bank_account": "BA0000QDWEEAFB",
      "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 will change status to `ready_to_fulfil`.
- This Billing Request can now be fulfilled by POST'ing to the [Fulfil a Billing Request Endpoint](https://developer.gocardless.com/api-reference#billing-requests-fulfil-a-billing-request)

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.

### Preventing Breaking Changes

#### 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](https://developer.gocardless.com/api-reference/#billing-request-flows-create-a-billing-request-flow) and send the payers through that flow.

### What’s next?

### Get started
