# Billing Request (Instant Bank Pay feature)

## Take a one-off Instant bank payment

### Create a Billing Request

---

**Note** 🇬🇧 🇩🇪 🇫🇷 🇮🇪 Instant Bank Pay supports GBP and EUR, available for transactions in GBP with your customers in the UK, and available for EUR with your customers in Germany, France, and Ireland. For payments in the UK, we also support [Direct Funds Settlement](https://developer.gocardless.com/direct-funds-settlement).

Create a Billing Request that specifies the payment you want to take from your customer using the `payment_request` object.

Our example will take a payment from an existing customer, by specifying the customer ID under `links.customer`. Leave this blank to set up a totally new customer.

Use the [Create a Billing Request](https://developer.gocardless.com/api-reference/#billing-requests-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" => [
    "payment_request" => [
      "description" => "First Payment",
      "amount" => "500",
      "currency" => "GBP",
      "app_fee" => "50",
    ],
  ]
]);
```

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

client.billing_requests.create(params={
  "payment_request": {
    "description": "First Payment",
    "amount": "500",
    "currency": "GBP",
    "app_fee": "50",
  },
})
```

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

@client.billing_requests.create(
  params: {
    payment_request: {
      description: "First Payment",
      amount: "500",
      currency: "GBP",
      app_fee: "50",
    },
  }
)
```

```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()
  .withPaymentRequestDescription("First Payment")
  .withPaymentRequestAmount(500)
  .withPaymentRequestCurrency(Currency.GBP)
  .withPaymentRequestAppFee(50)
  .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({
  payment_request: {
    description: "First Payment",
    amount: "500",
    currency: "GBP",
    app_fee: "50",
  },
});
```

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

var paymentRequest = new GoCardless.Services.BillingRequestCreateRequest.BillingRequestPaymentRequest
{
  Description = "First payment",
  Amount = 500,
  Currency = "GBP",
  AppFee = 50,
};

var resp = await gocardless.BillingRequests.CreateAsync(
  new GoCardless.Services.BillingRequestCreateRequest()
  {
    PaymentRequest = paymentRequest,
  }
);

GoCardless.Resources.BillingRequest billingRequest = resp.BillingRequest;
```

```HTTP
POST https://api.gocardless.com/billing_requests HTTP/1.1
{
  "billing_requests": {
    "payment_request": {
      "description": "First Payment",
      "amount": "500",
      "currency": "GBP",
      "app_fee": "50"
    },
  }
}

```

```go
package main

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

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{
	PaymentRequest: &gocardless.BillingRequestCreateParamsPaymentRequest{
		Amount: 500,
		Currency: "GBP",
		AppFee: 50,
		Description: "First Payment",
	},
}

billingRequest, err := client.BillingRequests.Create(context, billingRequestCreateParams)
```

```CLI
gc create billing_request \
  -d 'payment_request[amount]=500' \
  -d 'payment_request[app_fee]=50' \
  -d 'payment_request[currency]=GBP' \
  -d 'payment_request[description]="First Payment"'
```

You’ll receive a full Billing Request resource.

It will look like this:

```json
{
  "billing_requests": {
    "id": "BRQ123",
    "status": "pending",
    "mandate_request": null,
    "payment_request": {
      "currency": "GBP",
      "amount": "500",
      "description": "£5 Top Up",
      "scheme": "faster_payments"
    },
    "links": {
      "customer": "CU00016VR36GVW",
      "customer_billing_detail": "CBD000010M15PAC",
      "organisation": "OR123"
    }
  }
}
```

The Billing Request is currently pending, meaning we need to complete the outstanding actions before it can be fulfilled. We can use Billing Request Flows to generate a checkout flow that guides the payer through these actions.

Integrators building custom payment pages should read the [Billing Request actions](https://developer.gocardless.com/billing-requests/billing-request-actions) to understand what actions are available, and how to complete them.

If you complete actions yourself, you can resume this guide to have Billing Request Flows complete whatever remains.

### 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
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"
    }
  }
}
```

### Redirect customer to authorisation link

Share your **authorisation link **from the response in _Step 02_, 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.

### Implement a failsafe for optimised UX

---

Some customers may not be able to authorise the open banking transaction through the Billing Request Flow. This may happen if they are unable to use their mobile, they aren’t set up with online banking or the bank’s open banking API may be down.

To retain these customers and let them pay another way, you may pass an Exit URI which will send them wherever you choose in order to complete the transaction. It’s as simple as providing the address you’d like us to return the customer to.

#### **Provide an Exit URI when creating the Billing Request Flow  **

You may pass a `exit_uri` when creating the Billing Request Flow, the same way you pass the` redirect_uri`.

_Note: We recommend that you return customers to your checkout page, at the point of choosing a 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
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 includes the exit_uri being passed:

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

Customers will be sent to this URI when they click on the Exit URI in the Billing Request Flow.

#### Customer uses the Exit URL to return to your checkout

The Exit URL is shown if a customer is unable to find their bank, when searching the institution selector.

![ibp-uk-exit-url](https://images.ctfassets.net/b2dmfxhmyqno/2JtSEp5G24HjOreUWbkZ6z/a9140359f7ae60ac58d2e54e098ba9cf/5.jpg)

### Skipping components (relevant for existing customers)

As mentioned before if certain actions are already completed, or can be completed by another required action then we can skip them. The most common cases where a component may be skipped in the flow are as follows:

- **A Customer already exists**- in this case, we do not show the **CollectCustomerDetails** page however the user may be allowed to edit these details unless the customer has been locked (see* locking components* below)

![01-ibp-collect-customer-details](https://images.ctfassets.net/b2dmfxhmyqno/6enf9Jsr5lIyW0tcICAMmL/934311d4770f57a2a9928a7665ea900a/6.jpg)

- **A Bank account already exists**- in this case, we do not show the **CollectBankAccount** page however the user may be allowed to create a new bank account and use that for the payment unless the bank account has been locked (see locking components)

![ibp+mandate-collect-bank-details](https://images.ctfassets.net/b2dmfxhmyqno/4U7YC7ZLRHiTqjioIVMjVY/22181916c2f21b7c92a8c294a6417119/Screenshot_2024-01-11_at_11.30.32.png)

- **Bank authorisation allows the collection of banks**- in this case, if there are no existing banks, we will not ask the user to pick the bank account, instead, we use the details returned from the stage to create it

![06-mobile-handoff](https://images.ctfassets.net/b2dmfxhmyqno/3tlh3hWC6MSmAorzhAXJiP/10acd6b577e3172658a670790a013d1b/06-mobile-handoff.jpeg)

Existing customers or banks can be attached to the Billing Request when it is created, an example of this might be when creating a “top-up” single payment for a customer you already have a relationship with. [See API reference](https://developer.gocardless.com/api-reference/#billing-requests-create-a-billing-request)

### Locking components

Along with knowing the customer's details and the bank account you may wish to “lock” the request to only allow the customer to use those details. This allows you to ensure the payment is taken using details you have already collected for this customer in your own systems.

You can lock the customer, the bank account or both. This is done when creating the Billing Request Flow by setting `lock_customer_details` or `lock_bank_account` to true.

If a linked resource is locked the following happens:

- **Customer locked **- The **CollectCustomerDetails** page is not shown and the customer cannot open them for editing
- **Bank account locked **- The **CollectBankAccount** page is not shown and the customer cannot add another bank account to use instead

If both are locked then we skip almost every page and go directly to the confirmation page within the BankHandoff component. All the payer needs to do is confirm and possibly authenticate with the bank if it is required.

For mandate only requests, you may also "lock" the currency and scheme that the customer pays in. By default, mandate only requests have the currency/scheme "unlocked" so that the customer can set up their mandate in any of your available schemes. If you lock the currency, however, they will only be able to pay with the scheme you specified when creating the Billing Request. This can be useful if you only want to allow a customer to pay in one specific scheme.

This can be achieved by setting `lock_currency `to true on the Billing Request Flow. In this case a currency selector will not show in the payment page UI for the payer, and they will be unable to change currency.

### What the customer will see

### Customer fills in their personal details

Collect customer details in order to complete the billing request.

**Note:** this screen hides the input if details already exist, or the customer details have been locked.

![01-ibp-collect-customer-details](https://images.ctfassets.net/b2dmfxhmyqno/6enf9Jsr5lIyW0tcICAMmL/934311d4770f57a2a9928a7665ea900a/6.jpg)

### Customer selects their bank

Select the Bank account account in order for GC to take a payment.

![ibp-select-bank](https://images.ctfassets.net/b2dmfxhmyqno/37wt64YWh8b4sbOK3nYe64/abf4366aeae841cc59ddf65bbf5f3ea3/2.jpg)

### Customer is taken to their bank

Go to their bank to complete the authorisation. Customers can use the QR code to jump directly into their mobile banking app (this is the best UX in most cases) or opt to continue on their desktop.

![ibp-bank-connect-page](https://images.ctfassets.net/b2dmfxhmyqno/1fNEH5rL5S6b3IhLAXznAg/1224a09e6c7d4cf9ef51a5d42eadfce5/3.jpg)

### Confirmed!

![step-4: mandate setup](https://images.ctfassets.net/b2dmfxhmyqno/6oPH2pFs6A1mHTF1bwsWlQ/6a7bdc86b8256fd1d77aceaecdee87e4/step-4.png)

The mandate has now been created and is ready to create payments against. The Billing Request is fulfilled, and cannot be modified.

#### Done!

The payment has now been completed, and the Billing Request is `fulfilled`. Because this is an instant bank payment, the funds are confirmed within minutes of the request going through and leave the customer’s bank account immediately.

### What’s next?

### Get started
