# Recurring Payments

Source: https://docs.gocardless.com/docs/collect-payments/recurring-payments/subscriptions

# Subscriptions

## What are Subscriptions?

Automatically collect fixed amounts at regular intervals. Set up a subscription once, and GoCardless handles collection on schedule.

**When to use Subscriptions**

- SaaS subscriptions
- Membership fees
- Content subscriptions
- Gym memberships, insurance premiums, and ongoing services

## Comparison between other recurring payment options

**Key difference from instalments:** Instalment schedules have a defined end. Subscriptions continue indefinitely until cancelled.

|                        | Subscriptions                                        | Instalments                                    | Variable Recurring Payments                                                          | Instant Bank Pay + Direct Debit                          |
| ---------------------- | ---------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------------------- |
| Mandate required       | Yes                                                  | Yes                                            | Yes (consent)                                                                        | Yes                                                      |
| Customer authorisation | Once                                                 | Once                                           | Once (with agreed limits and frequency)                                              | Once                                                     |
| Payment amounts        | Fixed (per subscription)                             | Fixed per instalment, can vary across schedule | Variable within agreed constraints                                                   | First payment fixed; subsequent payments flexible        |
| Payment schedule       | Merchant-defined recurring (weekly, monthly, yearly) | Merchant-defined schedule with a defined end   | Flexible - merchant triggers payments as needed                                      | Flexible after first payment                             |
| Confirmation speed     | 2-x business days                                    | 2-x business days                              | Seconds                                                                              | First payment: minutes; subsequent: 2-x business days    |
| Chargeback risk        | Yes                                                  | Yes                                            | None                                                                                 | First payment: none; subsequent: yes                     |
| Missed payment retries | Yes (with Success+)                                  | Yes (with Success+)                            | Yes                                                                                  | Subsequent payments: yes                                 |
| Best for               | SaaS, memberships, gym fees, insurance               | Payment plans, tuition, professional services  | Usage-based regulated billing and utilities, financial services, government services | Subscription services needing immediate, initial payment |
| Availability           | All schemes                                          | All schemes                                    | GBP only                                                                             | GBP and EUR                                              |

**Need to change the amount?** If the amount varies between cycles, use one-off payments instead and control each charge individually. Alternatively, you can cancel and recreate a subscription with a new amount.

**Only taking payments for a defined period? **If the amount doesn't vary and you wish to only take a certain number of payments, use instalments instead.

## How it works

1. The customer sets up a mandate via your chosen integration
2. You create a payment against the mandate via the API
3. GoCardless collects the payment (typically 2-5 business days)
4. You receive a webhook confirming the payment status
5. Funds are included in your next payout

**Frequency options:** Weekly, monthly, yearly, or custom intervals.

## Step-by-step guide

### Create a billing request

```http
curl -X POST https://api.gocardless.com/billing_requests \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '
    }
  }'
```

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

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

$response = $client->billingRequests()->create([
    'params' => [
        'mandate_request' => [
            'scheme' => 'bacs',
        ],
    ],
]);
```

```python

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

response = client.billing_requests.create(
    params=
    }
)
```

```ruby
require 'gocardless_pro'

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

response = client.billing_requests.create(
  params: 
  }
)
```

```java

GoCardlessClient client = GoCardlessClient
    .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

BillingRequestCreateResponse response = client.billingRequests()
    .create()
    .withMandateRequestScheme("bacs")
    .execute();
```

```javascript
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(,
});
```

```cs
using GoCardless;

var client = GoCardlessClient.Create(
    Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"),
    GoCardlessClient.Environment.SANDBOX
);

var response = await client.BillingRequests.CreateAsync(
    new BillingRequestCreateRequest
    
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

func main() 

    params := gocardless.BillingRequestCreateParams,
    }

    result, err := client.BillingRequests.Create(context.TODO(), params)
    if err != nil 
    fmt.Println(result)
}
```

**Response:**

```json

  }
}
```

### Confirm the mandate

After creating the Billing Request, direct the customer to authorise the mandate. 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 Payment Pages](/integration-types/gocardless-hosted-pages).
- Custom API - Collect customer details and bank account via Billing Request actions, then confirm. See [Custom Payment Pages](/integration-types/custom-payment-pages).

### Handle the outcome

Once fulfilled, retrieve both mandate ID and payment ID from the billing request:

```http
curl https://api.gocardless.com/billing_requests/BRQ000123 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

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

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

$response = $client->billingRequests()->get('BRQ000123');

$mandateId = $response->mandate_request->links->mandate;
```

```python

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

response = client.billing_requests.get('BRQ000123')

mandate_id = response.mandate_request.links.mandate
```

```ruby
require 'gocardless_pro'

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

response = client.billing_requests.get('BRQ000123')

mandate_id = response.mandate_request.links.mandate
```

```java

GoCardlessClient client = GoCardlessClient
    .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

BillingRequest billingRequest = client.billingRequests()
    .get("BRQ000123")
    .execute();

String mandateId = billingRequest.getMandateRequest().getLinks().getMandate();
```

```javascript
const gocardless = require("gocardless-nodejs");
const constants = require("gocardless-nodejs/constants");

const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox);

const billingRequest = await client.billingRequests.find("BRQ000123");

const mandateId = billingRequest.mandate_request.links.mandate;
```

```cs
using GoCardless;

var client = GoCardlessClient.Create(
    Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"),
    GoCardlessClient.Environment.SANDBOX
);

var billingRequest = await client.BillingRequests.GetAsync("BRQ000123");

var mandateId = billingRequest.MandateRequest.Links.Mandate;
```

```go
package main

    "context"
    "fmt"
    "os"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

func main() 

    billingRequest, err := client.BillingRequests.Get(context.TODO(), "BRQ000123")
    if err != nil 

    mandateId := billingRequest.MandateRequest.Links.Mandate
    fmt.Println(mandateId)
}
```

**Response:**

```json

    }
  }
}
```

Listen for webhooks to confirm the payment status:

| Event                     | Meaning                          |
| ------------------------- | -------------------------------- |
| billing_request_fulfilled | Customer authorised the mandate  |
| mandates_created          | Mandate created and ready to use |
| mandates_active           | Mandate active                   |

### Handle the subscription

Once the mandate is active, set up recurring payments against it:

```http
curl -X POST https://api.gocardless.com/subscriptions \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '
    }
  }'
```

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

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

$response = $client->subscriptions()->create([
    'params' => [
        'amount'        => 2500,
        'currency'      => 'GBP',
        'name'          => 'Monthly Magazine',
        'interval_unit' => 'monthly',
        'interval'      => 1,
        'day_of_month'  => 1,
        'start_date'    => '2024-11-01',
        'links'         => [
            'mandate' => 'MD123',
        ],
    ],
]);
```

```python

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

response = client.subscriptions.create(
    params=,
    }
)
```

```ruby
  require 'gocardless_pro'

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

  response = client.subscriptions.create(
    params: 
    }
  )
```

```java

GoCardlessClient client = GoCardlessClient
    .newBuilder(System.getenv("GC_ACCESS_TOKEN"))
    .withEnvironment(GoCardlessClient.Environment.SANDBOX)
    .build();

Subscription subscription = client.subscriptions()
    .create()
    .withAmount(2500)
    .withCurrency("GBP")
    .withName("Monthly Magazine")
    .withIntervalUnit(Subscription.IntervalUnit.MONTHLY)
    .withInterval(1)
    .withDayOfMonth(1)
    .withStartDate("2024-11-01")
    .withLinksMandate("MD123")
    .execute();
```

```javascript
const gocardless = require("gocardless-nodejs");
const constants = require("gocardless-nodejs/constants");

const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox);

const subscription = await client.subscriptions.create(,
});
```

```cs
using GoCardless;

var client = GoCardlessClient.Create(
    Environment.GetEnvironmentVariable("GC_ACCESS_TOKEN"),
    GoCardlessClient.Environment.SANDBOX
);

var subscription = await client.Subscriptions.CreateAsync(
    new SubscriptionCreateRequest
    
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"
)

func main() 

    params := gocardless.SubscriptionCreateParams,
    }

    subscription, err := client.Subscriptions.Create(context.TODO(), params)
    if err != nil 
    fmt.Println(subscription)
}
```

**Response:**

```json
,
      
    ],
    "links": 
  }
}
```

### Manage the subscription

Listen for webhooks to confirm the mandate status and notifications about future payments:

| **Event**                     | **Meaning**                               |
| ----------------------------- | ----------------------------------------- |
| subscriptions_created         | Subscription set up successfully          |
| subscriptions_payment_created | A scheduled payment was created           |
| payments_confirmed            | Recurring payment collected successfully  |
| payments_failed               | Recurring payment failed                  |
| subscriptions_finished        | All payments collected (if count was set) |
| subscriptions_cancelled       | Subscription cancelled                    |

You can also cancel the subscription:

```http
curl -X POST https://api.gocardless.com/subscriptions/SB123/actions/cancel \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

```php
$response = $client->subscriptions()->cancel('SB123');
```

```python
response = client.subscriptions.cancel('SB123')
```

```ruby
response = client.subscriptions.cancel('SB123')
```

```java
Subscription subscription = client.subscriptions()
    .cancel("SB123")
    .execute();
```

```javascript
const client = gocardless(process.env.GC_ACCESS_TOKEN, constants.Environments.Sandbox);
```

```cs
var subscription = await client.Subscriptions.CancelAsync("SB123");
```

```go
subscription, err := client.Subscriptions.Cancel(context.TODO(), "SB123", gocardless.SubscriptionCancelParams)
```

Or pause the subscription:

```http
curl -X POST https://api.gocardless.com/subscriptions/SB123/actions/pause \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d ' }'
```

```php
$response = $client->subscriptions()->pause('SB123', [
    'params' => [
        'pause_cycles' => 3,
    ],
]);
```

```python
response = client.subscriptions.pause(
    'SB123',
    params=
)
```

```ruby
response = client.subscriptions.pause(
  'SB123',
  params: 
)
```

```java
Subscription subscription = client.subscriptions()
    .pause("SB123")
    .withPauseCycles(3)
    .execute();
```

```javascript
const subscription = await client.subscriptions.pause("SB123", );
```

```cs
var subscription = await client.Subscriptions.PauseAsync(
    "SB123",
    new SubscriptionPauseRequest
    
);
```

```go
params := gocardless.SubscriptionPauseParams

subscription, err := client.Subscriptions.Pause(context.TODO(), "SB123", params)
```

And resume the subscription:

```http
curl -X POST https://api.gocardless.com/subscriptions/SB123/actions/resume \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

```php
$response = $client->subscriptions()->resume('SB123');
```

```python
response = client.subscriptions.resume('SB123')
```

```ruby
response = client.subscriptions.resume('SB123')
```

```java
Subscription subscription = client.subscriptions()
    .resume("SB123")
    .execute();
```

```javascript
const subscription = await client.subscriptions.resume("SB123");
```

```cs
var subscription = await client.Subscriptions.ResumeAsync("SB123");
```

```go
subscription, err := client.Subscriptions.Resume(context.TODO(), "SB123", gocardless.SubscriptionResumeParams)
```

## What's next?

  
#### [Setting Up Mandates](/docs/collect-payments/setting-up-mandates)

Create mandates and collect bank account details via the API.

  
#### [Instalment Schedules](/docs/collect-payments/recurring-payments/instalment-schedules)

Define a series of payments with individual amounts and charge dates.

  
#### [Subscription Events](/docs/api-reference/events/subscriptions)

Understand the webhook events fired during subscription lifecycle.

  
#### [Success+](/docs/optimise/reduced-failed-payments-with-success-plus)

Automatically retry failed subscription payments.