Bacs Direct Debit for web
Last updated: September 2, 2026
Accept Bacs Direct Debit payments on your website with Flow, our pre-built, customizable payment user interface.
Flow enables you to accept payments using Checkout.com's global network of payment methods with a single integration.
Set up your client-side and server-side configuration to integrate with Checkout.com's payment gateway and enable payments on your website.
Bacs Direct Debit works differently from most payment methods in Flow. It does not take an immediate payment. Instead, it sets up a Direct Debit mandate, and you confirm the payment setup server-side after the mandate's five-day activation period passes.
- The customer lands on the checkout page.
- You perform a server-side request to create a payment session.
- You use the payment session data on the client-side to mount Flow.
- Flow displays the Bacs Direct Debit payment method to the customer.
- The customer chooses an individual or corporate account, enters their name or company name, email, sort code, and account number, and accepts the Direct Debit agreement.
- When the customer confirms, Flow creates a payment setup against the payment session and calls your
onMandateCreatedcallback with the setup ID. - You store the setup ID against your order.
- After the five-day mandate activation period, you call the Confirm a payment setup endpoint.
Make sure you have a test account with Checkout.com.
Create a public key and a secret key from the Dashboard, with the following key scopes:
- Public key –
payment-sessions:payandvault-tokenization - Secret key –
payment-sessions
To receive webhooks for the payment events, configure your webhook server.
To enable Bacs Direct Debit on your account, contact your account manager or request support.
If you have a Content Security Policy (CSP) on your website, Checkout.com requires the following directives:
1connect-src, https://*.checkout.com2frame-src, https://*.checkout.com3script-src, https://*.checkout.com4img-src, https://*.checkout.com
When the customer is ready to pay, you must send a server-side request to securely create a PaymentSession object. The PaymentSession contains the information required to handle all steps of the payment flow.
In your request:
- Set
billing.address.countrytoGB - Set
currencytoGBP - Set
payment_typetoRegularorRecurring - Provide
amount - Provide the
customer.emailorcustomer.id - Provide
items[] - For each
iteminitems[], provide the:namequantityreferenceunit_price
Information
For the full API specification, see the API reference.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
post
https://{prefix}.api.checkout.com/payment-sessions
1{2"amount": 1000,3"currency": "GBP",4"reference": "ORDER_01234",5"display_name": "Online shop",6"payment_type": "Regular",7"billing": {8"address": {9"country": "GB"10}11},12"customer": {13"name": "Hannah Bret",14"email": "hannah.bret@example.com"15},16"items": [17{18"reference": "0001",19"name": "Monthly subscription",20"quantity": 1,21"unit_price": 100022}23],24"success_url": "https://example.com/payments/success",25"failure_url": "https://example.com/payments/failure"26}
1{2"id": "ps_2Un6I6lRpIAiIEwQIyxWVnV9CqQ",3"payment_session_secret": "pss_9823241e-2cec-4c98-b23d-7b29ow4e2e34",4"payment_session_token": "YmFzZTY0:eyJpZCI6InBzXzJVbjZJNmxScElBaUlFd1FJeXhXVm5WOUNxUSIsIm...",5"_links": {6"self": {7"href": "https://{prefix}.api.sandbox.checkout.com/payment-sessions/ps_2Un6I6lRpIAiIEwQIyxWVnV9CqQ"8}9}10}
You can install the @checkout.com/checkout-web-components package via npm:
1npm install @checkout.com/checkout-web-components --save
Alternatively, you can load the package directly via a script:
1<script src="https://checkout-web-components.checkout.com/index.js" />
Note
To remain PCI compliant, only load the script directly from https://checkout-web-components.checkout.com. Do not download or host the script yourself, or include it in a bundle.
The client side initializes an instance of CheckoutWebComponents with configuration information and the payment session data retrieved in step 1.
1// Insert your public key here2const publicKey = '{YOUR_PUBLIC_KEY}';34const checkout = await CheckoutWebComponents({5paymentSession,6publicKey,7environment: 'sandbox',8});
The standard CheckoutWebComponents configuration options apply: appearance, componentOptions, environment, locale, paymentSession, publicKey, and translations. For more information, see the Flow library reference.
Use CheckoutWebComponents to create a bacs object.
1const bacsComponent = checkout.create('bacs');
Mount Flow to the website using the mount() method. The method takes an Element selector or an Element as an argument.
1if (await bacsComponent.isAvailable()) {2bacsComponent.mount('#bacs-container');3}
Note
Bacs Direct Debit requires a payment session. Unlike some other payment methods, you cannot use it in a session-less integration.
Note
Embedding Flow within an iframe or onto a Shadow DOM is not supported.
Bacs Direct Debit sets up a mandate rather than taking an immediate payment. Flow does not call the pay endpoint for Bacs. Instead, it creates a payment setup on the payment session.
This means Flow does not raise onPaymentCompleted for Bacs Direct Debit. You must handle the onMandateCreated callback to know that the Bacs setup completed successfully.
Flow raises onMandateCreated after it successfully creates the Direct Debit setup. It receives two arguments:
_self– The Bacs component instance, the same value passed to the other Flow callbacks.mandateContext– The payment setup response. Contains the payment method type and the setup ID.
The mandateContext argument has the following shape:
1{2"type": "bacs",3"context_data": {4"setup_id": "set_trelajtf9beufhpqy6mkkzf4ze"5}6}
You can set onMandateCreated on the Flow component, in which case it applies to the Bacs Direct Debit payment method inside Flow:
1const flowComponent = checkout.create('flow', {2onMandateCreated: (_self, mandateContext) => {3const setupId = mandateContext.context_data.setup_id;45// Store the setup ID against your order, then redirect the customer6window.location.href = `/confirmation?setup=${setupId}`;7},8onError: (_self, error) => {9console.error('Bacs setup failed', error);10},11});1213flowComponent.mount('#flow-container');
You can also set it directly on the Bacs component:
1const bacsComponent = checkout.create('bacs', {2onMandateCreated: (_self, mandateContext) => {3console.log('Mandate created', mandateContext.context_data.setup_id);4},5});
Note
After Flow creates the mandate, it moves the pay button into its success state and locks the form so the customer cannot resubmit. Perform your redirect to the confirmation page from inside onMandateCreated.
If the setup fails, Flow calls onError instead of onMandateCreated. The most common validation error codes for Bacs Direct Debit are:
modulus_error– The sort code and account number combination failed the modulus check.verification_error– We could not verify the bank details.invalid_data– The submitted data was invalid.
The onMandateCreated callback is not the end of the flow. Creating the mandate does not collect the payment.
After the five-day mandate activation period, take the setup ID you stored in step 3 and call the Confirm a payment setup endpoint.
If you do not confirm the payment setup, we never take the payment.
To check the status of a payment:
- Sign in to the Dashboard.
- Go to Payments > Processing > All payments.
- Select the test payment to view its details.