GoCardlessDeveloper Docs
Create a sandbox account

Pay By Bank#

View as Markdown

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 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 BankOne-off via Direct Debit
Mandate requiredNoYes
Customer authorisationPer paymentOnce (mandate setup)
Confirmation speedMinutes2-5 business days
Re-use for future paymentsNo, new authorisation each timeYes, collect again without re-authorisation
ProtectionNoneScheme-specific
Customer experienceThe bank app redirects each timeOne-time setup, then hands-off

If you expect to charge the customer more than once, a Direct Debit mandate 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 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#

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
require 'vendor/autoload.php';

$client = new \GoCardlessPro\Client([
'access_token' => 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',
],
],
]);
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',
}
}
)
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'
}
}
)
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();
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",
},
});
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"
}
}
);
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:

{
  "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.
  • Custom API — Collect customer details and bank account via Billing Request actions, then confirm. See Custom Payment Pages.

Handle the outcome#

Listen for webhooks to confirm the payment status:

EventMeaning
billing_request_fulfilledCustomer authorised, payment is being processed
payment_confirmedPayment confirmed and settled
payment_failedPayment failed (e.g., insufficient funds)

What's next?#