Now we’ve set up our first customer with a mandate, we’re ready to start taking payments. There are two ways to set up your payments - which one is right for you will depend on what you’re using GoCardless for:

  • One-off payments: Trigger a payment against a mandate at any time with the API. Great if you want to charge your customers ad-hoc amounts.
  • Subscriptions: Set up an automatic recurring payment. Great if you want to take the same payment on a regular basis (for instance £5 per week, or £20 on the first of each month).

You can even use these together - once you have a mandate, you have complete flexibility to charge your customers whenever you want.

Let’s try both - we’d recommend spending a few minutes on each to get to understand the full power of the API.

Using one-off payments

Let’s start by collecting a payment of £10 from the customer we just created:

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

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$payment = $client->payments()->create([
  "params" => [
      "amount" => 1000, // 10 GBP in pence
      "currency" => "GBP",
      "links" => [
          "mandate" => "MD0000XH9A3T4C"
                       // The mandate ID from last section
      ],
      // Almost all resources in the API let you store custom metadata,
      // which you can retrieve later
      "metadata" => [
          "invoice_number" => "001"
      ]
  ],
  "headers" => [
      "Idempotency-Key" => "random_payment_specific_string"
  ]
]);

// Keep hold of this payment ID - we'll use it in a minute
// It should look like "PM000260X9VKF4"
print("ID: " . $payment->id);
import os
import gocardless_pro

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

payment = client.payments.create(
    params={
        "amount" : 1000, # 10 GBP in pence
        "currency" : "GBP",
        "links" : {
            "mandate": "MD0000XH9A3T4C"
                     # The mandate ID from the last section
        },
        # Almost all resources in the API let you store custom metadata,
        # which you can retrieve later
        "metadata": {
          "invoice_number": "001"
        }
    }, headers={
        'Idempotency-Key' : 'random_key',
})

# Keep hold of this payment ID - we will use it in a minute
# It should look like "PM000260X9VKF4"
print("ID: {}".format(payment.id))
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
	access_token: ENV['GC_ACCESS_TOKEN'],
	environment: :sandbox
)

payment = client.payments.create(
  params: {
    amount: 1000, # 10 GBP in pence
    currency: 'GBP',
    links: {
      mandate: 'MD0000XH9A3T4C'
             # The mandate ID from last section
    },
    # Almost all resources in the API let you store custom metadata,
    # which you can retrieve later
    metadata: {
      invoice_number: '001'
    }
  },
  headers: {
    'Idempotency-Key' => 'random_payment_specific_string'
  }
)

# Keep hold of this payment ID - we will use it in a minute
# It should look like "PM000260X9VKF4"
puts "ID: #{payment.id}"
package com.gcintegration;

import com.gocardless.GoCardlessClient;
import com.gocardless.resources.Payment;
import com.gocardless.services.PaymentService.PaymentCreateRequest.Currency;

public class SinglePayment {
    public static void main(String[] args) {
        GoCardlessClient client = GoCardlessClient
            .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
            .withEnvironment(GoCardlessClient.Environment.SANDBOX)
            .build();

        Payment payment = client.payments().create()
            .withAmount(1000) // 10 GBP in pence
            .withCurrency(Currency.GBP)
            .withLinksMandate("MD0000XH9A3T4C")
            .withMetadata("invoice_number", "001")
            .withIdempotencyKey("random_payment_specific_string")
            .execute();
        // Keep hold of this payment ID - we'll use it in a minute
        // It should look like "PM000260X9VKF4"
        System.out.println(payment.getId());
    }
}
var createResponse = await client.Payments.CreateAsync(new PaymentCreateRequest()
{
    Amount = 1000,
    Currency = PaymentCreateRequest.PaymentCurrency.GBP,
    Links = new PaymentCreateRequest.PaymentLinks()
    {
        Mandate = "MD0000XH9A3T4C",
    },
    Metadata = new Dictionary<string, string>()
    {
        {"invoice_number", "001"}
    },
    IdempotencyKey = "random_payment_specific_string"
});

Payment payment = createResponse.Payment;

// Keep hold of this payment ID - we'll use it in a minute
// It should look like "PM000260X9VKF4"
Console.WriteLine(payment.Id);

You’ll need to use the currency appropriate for the mandate you set up. This depends on what Direct Debit scheme you are using - the scheme of your mandate set up through the redirect flow will depend on your location (though you can set it manually by specifying a scheme):

Location currency
UK GBP
Sweden SEK
Denmark DKK
Australia AUD
New Zealand NZD
Canada CAD
Everywhere else EUR
You’ll notice here that we provide an Idempotency-Key header. If we provide a unique string specific to this payment (for example its ID in our own database), the API will ensure this payment is only ever created once.

This means that if an API request times out or something goes wrong on your end, you won’t ever accidentally bill a customer twice - see our blog post for more details. You can use idempotency keys whenever you create something with the API.

In the live environment, £10 would be collected from the customer’s bank account and then paid out to you. Since we’re in the sandbox, this won’t happen, but the payment will progress with realistic timings as though it was really being processed.

If you head to your dashboard, you’ll be able to see the payment you’ve just created.

If you're creating payments in bulk (or making many requests in a short period for any other reason), you'll need to make sure you don't exceed our rate limit and handle any 429 Too Many Requests errors appropriately. You can make up to 1000 requests per minute.

Much like listing customers with list() as we did earlier, we can fetch an individual resource from the API at any time using its ID.

Once you have the ID, you can also perform useful functions on the payment, like cancelling it or retrying it if it has failed.

Let’s try grabbing our payment, and then cancelling it, taking a look at its status before and after:

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

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$payment = $client->payments()->get("PM000260X9VKF4");
                              // Payment ID from above

print("Status: " . $payment->status . "<br />");
print("Cancelling...<br />");

$payment = $client->payments()->cancel("PM000260X9VKF4");
print("Status: " . $payment->status);
import os
import gocardless_pro

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

payment = client.payments.get("PM000260X9VKF4")
                         # Payment ID from above.

print("Amount: {}".format(payment.amount))
print("Cancelling...")

payment = client.payments.cancel("PM000260X9VKF4")
print("Status: {}".format(payment.status))
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
	access_token: ENV['GC_ACCESS_TOKEN'],
	environment: :sandbox
)

payment = client.payments.get('PM000269VJAR6M')
                         # Payment ID from above.

puts "Status: #{payment.status}"
puts 'Cancelling...'

payment = client.payments.cancel('PM000269VJAR6M')
puts "Status: #{payment.status}"
package com.gcintegration;

import com.gocardless.GoCardlessClient;
import com.gocardless.resources.Payment;

public class CancelPayment {
    public static void main(String[] args) {
        GoCardlessClient client = GoCardlessClient
            .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
            .withEnvironment(GoCardlessClient.Environment.SANDBOX)
            .build();

        Payment payment = client.payments().get("PM000260X9VKF4").execute();
                                              // Payment ID from above.
        System.out.printf("Amount: %s%n", payment.getAmount());
        System.out.println("Cancelling...");

        payment = client.payments().cancel("PM000260X9VKF4").execute();
        System.out.printf("Status: %s%n", payment.getStatus());
    }
}
// Payment ID from above
String paymentId = "PM000260X9VKF4";

var paymentResponse = await client.Payments.GetAsync(paymentId);
Payment payment = paymentResponse.Payment;

Console.WriteLine($"Amount: {payment.Amount}");
Console.WriteLine("Cancelling...");

var cancelResponse = await client.Payments.CancelAsync(paymentId);
payment = cancelResponse.Payment;
Console.WriteLine($"Status: {payment.Status}");

Using subscriptions

Now, let’s create a subscription. Subscriptions collect a fixed, regular amount from a customer.

Let’s try collecting £15 per month on the 5th of each month from our customer:

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

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$subscription = $client->subscriptions()->create([
  "params" => [
      "amount" => 1500, // 15 GBP in pence
      "currency" => "GBP",
      "interval_unit" => "monthly",
      "day_of_month" => "5",
      "links" => [
          "mandate" => "MD0000XH9A3T4C"
                       // Mandate ID from the last section
      ],
      "metadata" => [
          "subscription_number" => "ABC1234"
      ]
  ],
  "headers" => [
      "Idempotency-Key" => "random_subscription_specific_string"
  ]
]);

// Keep hold of this subscription ID - we'll use it in a minute.
// It should look a bit like "SB00003GKMHFFY"
print("ID: " . $subscription->id);
import os
import gocardless_pro

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

subscription = client.subscriptions.create(
    params={
        "amount" : 1500, # 15 GBP in pence    
        "currency" : "GBP",
        "interval_unit" : "monthly",
        "day_of_month" : "5",
        "links": {
            "mandate": "MD0000XH9A3T4C"
                     # Mandate ID from the last section
        },
        "metadata": {
            "subscription_number": "ABC1234"
        }
    }, headers={
        'Idempotency-Key': "random_subscription_specific_string"
})

# Keep hold of this subscription ID - we'll use it in a minute
# It should look a bit like "SB00003GKMHFFY"
print("ID: {}".format(subscription.id))
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
	access_token: ENV['GC_ACCESS_TOKEN'],
	environment: :sandbox
)

subscription = client.subscriptions.create(
  params: {
    amount: 1500, # 15 GBP in pence
    currency: 'GBP',
    interval_unit: 'monthly',
    day_of_month: '5',
    links: {
      mandate: 'MD0000XH9A3T4C'
              # Mandate ID from the last section
    },
    metadata: {
      subscription_number: 'ABC1234'
    }
  },
  headers: {
    'Idempotency-Key': 'random_subscription_specific_string'
  }
)

# Keep hold of this subscription ID - we'll use it in a minute
# It should look a bit like "SB00003GKMHFFY"
puts "ID: #{subscription.id}"
package com.gcintegration;

import com.gocardless.GoCardlessClient;
import com.gocardless.resources.Subscription;
import com.gocardless.services.SubscriptionService.SubscriptionCreateRequest.IntervalUnit;

public class CreateSubscription {
    public static void main(String[] args) {
        GoCardlessClient client = GoCardlessClient
            .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
            .withEnvironment(GoCardlessClient.Environment.SANDBOX)
            .build();

        Subscription subscription = client.subscriptions().create()
            .withAmount(1500) // 15 GBP in Pence
            .withCurrency("GBP")
            .withIntervalUnit(IntervalUnit.MONTHLY)
            .withDayOfMonth(5)
            .withLinksMandate("MD0000YTKZKY4J")
                             // Mandate ID from the last section
            .withMetadata("subscription_number", "ABC123")
            .withIdempotencyKey("random_subscription_specific_string")
            .execute();

        // Keep hold of this subscription ID - we'll use it in a minute.
        // It should look a bit like "SB00003GKMHFFY"
        System.out.printf("ID: %s%n", subscription.getId());
    }
}
var createResponse = await client.Subscriptions.CreateAsync(new SubscriptionCreateRequest
{
    Amount = 1500,
    Currency = "GBP",
    Name = "Monthly subscription",
    Interval = 1,
    IntervalUnit = SubscriptionCreateRequest.SubscriptionIntervalUnit.Monthly,
    DayOfMonth = 5,
    Links = new GoCardless.Services.SubscriptionCreateRequest.SubscriptionLinks
    {
        Mandate = "MD0123"
    },
    IdempotencyKey = "unique_subscription_specific_string"
});

var subscription = createResponse.Subscription;

Console.WriteLine(subscription.Id);

You may need to change the currency depending on your location.

Each month, on the 5th of the month, the subscription will generate a new payment for £15 to be collected from the customer.

With the subscription ID, we can grab the subscription from the API. Let’s then try cancelling it so that no further payments are taken:

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

$client = new \GoCardlessPro\Client([
    'access_token' => getenv('GC_ACCESS_TOKEN'),
    'environment' => \GoCardlessPro\Environment::SANDBOX
]);

$subscription = $client->subscriptions()->get("SB00003GKMHFFY");
                                        // Subscription ID from above.

print("Status: " . $subscription->status . "<br />");
print("Cancelling...<br />");

$subscription = $client->subscriptions()->cancel("SB00003GKMHFFY");

print("Status: " . $subscription->status . "<br />");
import os
import gocardless_pro

client = gocardless_pro.Client(
    access_token=os.environ['GC_ACCESS_TOKEN'],
    environment='sandbox'
)

subscription = client.subscriptions.get("SB00003GKMHFFY")
                                   # Subscription ID from above.

print("Status: {}".format(subscription.status))
print("Cancelling...")

subscription = client.subscriptions.cancel("SB00003GKMHFFY")

print("Status: {}".format(subscription.status))
require 'gocardless_pro'

client = GoCardlessPro::Client.new(
	access_token: ENV['GC_ACCESS_TOKEN'],
	environment: :sandbox
)

subscription = client.subscriptions.get('SB00003GKMHFFY')
                                   # Subscription ID from above.

puts "Status: #{subscription.status}"
puts 'Cancelling...'

subscription = client.subscriptions.cancel('SB00003GKMHFFY')
puts "Status: #{subscription.status}"
package com.gcintegration;

import com.gocardless.GoCardlessClient;
import com.gocardless.resources.Subscription;

public class CancelSubscription {
    public static void main(String[] args) {
        GoCardlessClient client = GoCardlessClient
            .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
            .withEnvironment(GoCardlessClient.Environment.SANDBOX)
            .build();

        Subscription subscription = client.subscriptions().get("SB00003GKMHFFY").execute();

        System.out.printf("Amount: %s%n", subscription.getStatus());
        System.out.println("Cancelling...");

        subscription = client.subscriptions().cancel("SB00003GKMHFFY").execute();

        System.out.printf("Status: %s%n", subscription.getStatus());
    }
}
// Subscription ID from above
String subscriptionId = "SB00003GKMHFFY";

var subscriptionResponse = await client.Subscriptions.GetAsync(subscriptionId);
Subscription subscription = subscriptionResponse.Subscription;

Console.WriteLine($"Amount: {subscription.Amount}");
Console.WriteLine("Cancelling...");

var cancelResponse = await client.Subscriptions.CancelAsync(subscriptionId);
subscription = cancelResponse.Subscription;
Console.WriteLine($"Status: {subscription.Status}");