You’ll need to provide a way for your users to set up Direct Debit mandates with their customers (whom we’ll refer to from now on as “end customers”) so they can start collecting payments from them.

A mandate allows you to pull money from an end customer’s bank account with a simple API call.

Two ways to add customers

You have two options for setting up Direct Debit mandates:

  • Use our secure, hosted payment pages: GoCardless provides secure, hosted, mobile-friendly, conversion-optimised payment pages that have been translated into many European languages and comply with the “scheme rules” of the Direct Debit schemes. You redirect the customer to us, they provide their bank details on our site, and then we send them back to your application. You never have to handle end customers’ bank details.
  • Build your own Direct Debit setup process: Rather than use our ready-made flow, you can build your own. If you’d like to do this, please contact our partnerships team who’ll be able to explain the process.

In this guide, we’ll take you through using our hosted payment pages, which we call the “Redirect Flow”. To set up a mandate, you’ll generate a link to the Redirect Flow using the API, and send the customer there where they’ll enter their details.

Setting up Direct Debit mandates

At this point, it’s worth thinking through how your users will want to send their end customers to the Direct Debit setup flow - making this work in a way which suits their workflow and how they use your product will hugely improve their experience. Here are some ideas you might like to consider:

  • In KashFlow, end customers can set up a Direct Debit by clicking a button on their invoice
  • In GoCardless for Xero, users collecting payments can copy a personalised link to allow a customer to set up a Direct Debit, ready to paste into their own emails or add as a link on their website
  • In the GoCardless Dashboard, users collecting payments can send an email to a customer in one click with their own customised copy, asking them to set up a Direct Debit, either for a single customer or for tens or hundreds at a time

You can read some of our suggestions on the best ways for your users to send their end customers to the Direct Debit setup flow in our user experience guide.

Whatever the experience looks like for setting up mandates from your user’s point of view, the code for generating the link looks identical:

<?php
require 'vendor/autoload.php';

$client = new \GoCardlessPro\Client([
    // You'll need to identify the user that the customer is paying and fetch their
    // access token
    'access_token' => $user->gocardlessAccessToken,
    // Change me to LIVE when you're ready to go live
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$redirectFlow = $client->redirectFlows()->create([
    "params" => [
        // A description of what the Direct Debit is for to be shown to the customer
        "description" => "Automatic invoice payments to Acme plc",
        // A unique token for the customer's session
        "session_token" => "dummy_session_token",
        // The URL for a success page you host, to send the customer to when they finish
        "success_redirect_url" => "https://developer.gocardless.com/example-redirect-uri/",
        // Optionally, prefill customer details on the payment page
        "prefilled_customer" => [
            "given_name" => "Tim",
            "family_name" => "Rogers",
            "email" => "tim@gocardless.com",
            "address_line1" => "338-346 Goswell Road",
            "city" => "London",
            "postal_code" => "EC1V 7LQ"
        ]
    ]
]);

// You'll need to redirect the end customer to this URL.
print("URL: " . $redirectFlow->redirect_url);
import os
import gocardless_pro

client = gocardless_pro.Client(
    # You'll need to identify the user that the customer is paying and fetch their
    # access token
    access_token=user.gocardless_access_token,
    # Change this to 'live' when you are ready to go live.
    environment='sandbox'
)

redirect_flow = client.redirect_flows.create(
    params={
        # A description of what the Direct Debit is for to be shown to the customer
        "description" : "Automatic invoice payments to Acme plc",
        # A unique token for the customer's session
        "session_token" : "dummy_session_token",
        # The URL for a success page you host, to send the customer to when they finish
        "success_redirect_url" : "https://developer.gocardless.com/example-redirect-uri/",
        # Optionally, prefill customer details on the payment page
        "prefilled_customer": {
            "given_name": "Tim",
            "family_name": "Rogers",
            "email": "tim@gocardless.com",
            "address_line1": "338-346 Goswell Road",
            "city": "London",
            "postal_code": "EC1V 7LQ"
        }
    }
)

# You'll need to redirect the end customer to this URL.
print("URL: {} ".format(redirect_flow.redirect_url))
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
  # You'll need to identify the user that the customer is paying and fetch their
  # access token
  access_token: user.gocardless_access_token,
  # Remove the following line when you're ready to go live
  environment: :sandbox
)

redirect_flow = client.redirect_flows.create(
  params: {
    # A description of what the Direct Debit is for to be shown to the customer
    description: 'Automatic invoice payments to Acme plc',
    # A unique token for the customer's session
    session_token: 'dummy_session_token',
    # The URL for a success page you host, to send the customer to when they finish
    success_redirect_url: 'https://developer.gocardless.com/example-redirect-uri/',
    # Optionally, prefill customer details on the payment page
    prefilled_customer: {
      given_name: 'Tim',
      family_name: 'Rogers',
      email: 'tim@gocardless.com',
      address_line1: '338-346 Goswell Road',
      city: 'London',
      postal_code: 'EC1V 7LQ'
    }
  }
)

# You'll need to redirect the end customer to this URL.
puts "URL: #{redirect_flow.redirect_url}"
package com.gcintegration;

import com.gocardless.GoCardlessClient;
import com.gocardless.resources.RedirectFlow;

GoCardlessClient client = GoCardlessClient
    // You'll need to identify the user that the customer is paying and fetch their
    // access token
    .newBuilder(CurrentUser.gocardlessAccessToken)
    // Change me to LIVE when you're ready to go live
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

RedirectFlow redirectFlow = client.redirectFlows().create()
    // A description of what the Direct Debit is for to be shown to the customer
    .withDescription("Automatic invoice payments to Acme plc")
    // A unique token for the customer's session
    .withSessionToken("dummy_session_token")
    // The URL for a success page you host, to send the customer to when they
    // finish
    .withSuccessRedirectUrl("https://developer.gocardless.com/example-redirect-uri/")
    // Optionally, prefill customer details on the payment page
    .withPrefilledCustomerGivenName("Tim")
    .withPrefilledCustomerFamilyName("Rogers")
    .withPrefilledCustomerEmail("tim@gocardless.com")
    .withPrefilledCustomerAddressLine1("338-346 Goswell Road")
    .withPrefilledCustomerCity("London")
    .withPrefilledCustomerPostalCode("EC1V 7LQ")
    .execute();

// You'll need to redirect the end customer to this URL.
System.out.println(redirectFlow.getRedirectUrl());
var redirectFlowResponse = await client.RedirectFlows.CreateAsync(new RedirectFlowCreateRequest
{
    Description = "Cider Barrels",
    SessionToken = "dummy_session_token",
    SuccessRedirectUrl = "https://developer.gocardless.com/example-redirect-uri/",
    // Optionally, prefill customer details on the payment page
    PrefilledCustomer = new RedirectFlowCreateRequest.RedirectFlowPrefilledCustomer
    {
        GivenName = "Tim",
        FamilyName = "Rogers",
        Email = "tim@gocardless.com",
        AddressLine1 = "338-346 Goswell Road",
        City = "London",
        PostalCode = "EC1V 7LQ"
    }
});

var redirectFlow = redirectFlowResponse.RedirectFlow;

// Hold on to this ID - you'll need it when you
// "confirm" the redirect flow later
Console.WriteLine(redirectFlow.Id);
Console.WriteLine(redirectFlow.RedirectUrl);

You’ll need to customise this code snippet with a few details of your own:

  • Substitute in your user’s GoCardless access token, which you stored when they completed the OAuth Flow
  • Provide a helpful description which will be shown to the end customer, explaning what their payments are for (e.g. “Automatic invoice payments to Acme plc” or “Monthly membership payments to Peckham Pikes Swimming Club”)
  • Set the success_redirect_url to where you want us to send the customer once they’ve finished the Direct Debit setup flow (you’ll need to make an API call from this page to “complete” the redirect flow - this will be explained below)
  • Pass in a session_token which identifies the end customer’s session on your website (for example their session ID in your application). You provide this when creating the redirect flow, and must provide it again when “completing” it at the end. Supplying this token twice makes sure that the person who completed the redirect flow is the person you sent to it.
  • Optionally, you can include a prefilled_customer object with your end customer’s details. These will be pre-filled on the payment page so your customer doesn’t have to enter them. For a full list of the details you can provide, head to the API reference.

You’ll get back a URL which will look something like https://pay-sandbox.gocardless.com/flow/RE00006GBDVVP3BBCP9Q5318ZVJWE0DN - redirect the end customer to this link where they’ll be able to enter their details and set up their mandate.

Links to the Redirect Flow will expire after a few minutes - this means that you can't include it directly in emails to your user's customers or give it to your users to copy and paste, but rather, must link to a page on your server which will generate a link on the fly.

While you’re testing the mandate setup process in the sandbox, you can use the following sample bank details:

  • In the UK, use the sort code 200000 and the account number 55779911
  • In Sweden, use the clearingnummer (branch code) 5491, the kontonummer (account number) 0000003 and the personnummer (Swedish identity number) 198112289874
  • In Denmark, use the registreringsnummer (bank code) 345, the kontonummer (account number) 3179681 and the CPR-nummer (Danish identity number) 0101701234
  • In Australia, use the BSB 082-082 and the account number 012345678
  • In New Zealand, use the bank code 12, branch code 3113 and the account number 0003869-00
  • In Canada, use the bank code (Financial Institution number) 0003, branch code (Branch Transit number) 00006 and the account number 0000000
  • Everywhere else, use the French IBAN FR1420041010050500013M02606

When you’re building an integration with the API, there are some common paths you should make sure your integration handles successfully, for example a customer cancelling their mandate or a payment failing due to lack of funds. We’ll look at handling these cases later.

In the sandbox environment, we provide scenario simulators which allow you to manually trigger certain cases (like a customer cancelling their mandate or a payment failing due to insufficient funds) from the Dashboard so you can test how your integration responds.

Completing the redirect flow

Once the end customer finishes filling out our payment pages, they’ll be redirected to your success_redirect_url. On this page, you’ll need to use a second API call to “complete” the redirect flow. You’ll need the ID of the redirect flow, passed to you in the redirect_flow_id query parameter, plus the session_token we set earlier:

<?php
require 'vendor/autoload.php';

$client = new \GoCardlessPro\Client([
    // You'll need to identify the user that the customer is paying and fetch their
    // access token - you might store this in the end customer's session, for example
    'access_token' => $user->gocardlessAccessToken,
    // Change me to LIVE when you're ready to go live
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$redirectFlow = $client->redirectFlows()->complete(
    $_GET['redirect_flow_id'], // The value of the `redirect_flow_id` query parameter
    ["params" =>
        ["session_token" => "dummy_session_token"] // The session token specified earlier
    ]
);

// Store the mandate ID against the customer's database record so you can charge
// them in future
print("Mandate: " . $redirectFlow->links->mandate . "<br />");
print("Customer: " . $redirectFlow->links->customer . "<br />");

// Display a confirmation page to the customer, telling them their Direct Debit has been
// set up. You could build your own, or use ours, which shows all the relevant
// information and is translated into all the languages we support.
print("Confirmation URL: " . $redirectFlow->confirmation_url . "<br />");
import os
import gocardless_pro

client = gocardless_pro.Client(
    # You'll need to identify the user that the customer is paying and fetch their access
    # token - you might store this in the end customer's session, for example
    access_token=user.gocardless_access_token,
    #Change this to 'live' when you are ready to go live.
    environment='sandbox'
)

redirect_flow = client.redirect_flows.complete(
    "RE00006GBASX53T7KYWT4051FMC0TZA6", # The value of the `redirect_flow_id` query parameter
    params={
        "session_token": "dummy_session_token" // The session token you specified earlier
})

# Store the mandate ID against the customer's database record so you can charge them in
# future
print("Mandate: {}".format(redirect_flow.links.mandate))
print("Customer: {}".format(redirect_flow.links.customer))

# Display a confirmation page to the customer, telling them their Direct Debit has been
# set up. You could build your own, or use ours, which shows all the relevant
# information and is translated into all the languages we support.
print("Confirmation URL: {}".format(redirect_flow.confirmation_url))
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
  # You'll need to identify the user that the customer is paying and fetch their access
  # token - you might store this in the end customer's session, for example
	access_token: user.gocardless_access_token,
	environment: :sandbox
)

redirect_flow = client.redirect_flows.complete(
    params['redirect_flow_id'], # The value of the `redirect_flow_id` query parameter
    params: { session_token: 'dummy_session_token' }) # The session token you specified earlier

# Store the mandate ID against the customer's database record so you can charge them in
# future
puts "Mandate: #{redirect_flow.links.mandate}"
puts "Customer: #{redirect_flow.links.customer}"

# Display a confirmation page to the customer, telling them their Direct Debit has been
# set up. You could build your own, or use ours, which shows all the relevant
# information and is translated into all the languages we support.
puts "Confirmation URL: #{redirect_flow.confirmation_url}"
package com.gcintegration;

import com.gocardless.GoCardlessClient;
import com.gocardless.resources.RedirectFlow;

GoCardlessClient client = GoCardlessClient
    // You'll need to identify the user that the customer is paying and fetch their
    // access token - you might store this in the end customer's session, for example
    .newBuilder(user.gocardlessAccessToken)
    // Change me to LIVE when you're ready to go live
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

RedirectFlow redirectFlow = client.redirectFlows()
        .complete("RE00007201VQ3H3HSTM2V02BYG4DPF1S")
                  // The value of the `redirect_flow_id` query parameter
        .withSessionToken("dummy_session_token")
                          // The session token you specified earlier
        .execute();

// Store the mandate ID against the customer's database record so you can charge
// them in future
System.out.println(redirectFlow.getLinks().getMandate());
System.out.println(redirectFlow.getLinks().getCustomer());

// Display a confirmation page to the customer, telling them their Direct Debit has been
// set up. You could build your own, or use ours, which shows all the relevant
// information and is translated into all the languages we support.
System.out.println(redirectFlow.getConfirmationUrl());
var redirectFlowResponse = await client.RedirectFlows
    .CompleteAsync("RE00007201VQ3H3HSTM2V02BYG4DPF1S",
        new RedirectFlowCompleteRequest
        {
            SessionToken = "dummmy_session_token"
        }
    );

var redirectFlow = redirectFlowResponse.RedirectFlow;

// Store the mandate ID against the customer's database record so you can charge
// them in future
Console.WriteLine($"Mandate: {redirectFlow.Links.Mandate}");
Console.WriteLine($"Customer: {redirectFlow.Links.Customer}");

// Display a confirmation page to the customer, telling them their Direct Debit has been
// set up. You could build your own, or use ours, which shows all the relevant
// information and is translated into all the languages we support.
Console.WriteLine($"Confirmation URL: {redirectFlow.ConfirmationUrl}");

The complete method returns the redirect flow object, now including details of the mandate, customer and customer bank account that have been created.

You’ll want to store the mandate ID in your database, associated with the end customer (for example, if you’re building an product for managing memberships to a sports club, you’d store it in the database attached to the database record representing the member). We’d suggest storing the mandates in a separate database table so you can more easily keep track of mandates over their whole lifecycle and handle multiple mandates per customer - we’ll learn more about that later.

With the redirect flow completed and the mandate ID stored, show the end customer a clear confirmation page telling them that their Direct Debit has been set up, and what will happen next.

You could build your own (we’ve included some more thoughts on this in our user experience guide), or you could use our pre-made one which comes ready translated into all the languages we support - just redirect the customer to the URL found in the confirmation_url attribute of the redirect flow.

Our provided confirmation page is only available for 15 minutes from the moment when you complete the redirect flow via the API, so you should redirect the customer straight to it.

GoCardless's ready-made confirmation page