# Instalments

## What are Instalments?

Spread the cost of a purchase over a defined number of fixed payments. You specify the total amount, number of instalments, and schedule; GoCardless handles the rest.

**Card: Instalments - When to use**

**When to use Instalments**

- Payment plans for high-ticket purchases
- Tuition and course fees
- Professional services (accounting, legal)
- Healthcare and dental treatment plans

---

## Comparison between other recurring payment options

**Key difference from subscriptions:** 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                                              |

---

## How it works

1. The customer sets up a mandate
2. You create an instalment schedule specifying the total amount, the number of payments, and the frequency
3. GoCardless automatically creates and collects each instalment
4. The schedule completes after the final instalment

**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 '{
    "billing_requests": {
      "mandate_request": {
        "scheme": "bacs"
      }
    }
  }'
```

```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
import os
import gocardless_pro

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

response = client.billing_requests.create(
    params={
        'mandate_request': {
            'scheme': 'bacs',
        }
    }
)
```

```ruby
require 'gocardless_pro'

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

response = client.billing_requests.create(
  params: {
    mandate_request: {
      scheme: 'bacs'
    }
  }
)
```

```java
import com.gocardless.GoCardlessClient;

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({
  mandate_request: {
    scheme: "bacs",
  },
});
```

```.net
using GoCardless;

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

var response = await client.BillingRequests.CreateAsync(
    new BillingRequestCreateRequest
    {
        MandateRequest = new BillingRequestCreateRequest.BillingRequestMandateRequest
        {
            Scheme = "bacs"
        }
    }
);
```

```go
package main

import (
    "context"
    "fmt"
    "os"

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

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{
        MandateRequest: &gocardless.BillingRequestCreateParamsMandateRequest{
            Scheme: "bacs",
        },
    }

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

**Response:**

```json
{
  "billing_requests": {
    "id": "BRQ000123",
    "status": "pending",
    "mandate_request": {
      "currency": "GBP",
      "scheme": "bacs"
    }
  }
}
```

### 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
import os
import gocardless_pro

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
import com.gocardless.GoCardlessClient;

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;
```

```.net
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

import (
    "context"
    "fmt"
    "os"

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

func main() {
    opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint)
    client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts)
    if err != nil {
        panic(err)
    }

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

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

**Response:**

```json
{
  "billing_requests": {
    "id": "BRQ000123",
    "status": "fulfilled",
    "mandate_request": {
      "scheme": "bacs",
      "links": {
        "mandate": "MD123"
      }
    }
  }
}
```

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                   |

### Setup the instalments

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

**Option A** - Create the instalment plan with fixed dates (you specify each exact charge date):

```http
curl -X POST https://api.gocardless.com/instalment_schedules \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "instalment_schedules": {
      "name": "Invoice #1234",
      "currency": "GBP",
      "total_amount": 2500,
      "instalments": [
        { "amount": 1500, "charge_date": "2024-11-01" },
        { "amount": 1000, "charge_date": "2025-02-01" }
      ],
      "links": {
        "mandate": "MD123"
      }
    }
  }'
```

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

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

$response = $client->instalmentSchedules()->createWithDates([
    'params' => [
        'name'         => 'Invoice #1234',
        'currency'     => 'GBP',
        'total_amount' => 2500,
        'instalments'  => [
            ['amount' => 1500, 'charge_date' => '2024-11-01'],
            ['amount' => 1000, 'charge_date' => '2025-02-01'],
        ],
        'links' => [
            'mandate' => 'MD123',
        ],
    ],
]);
```

```python
import os
import gocardless_pro

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

response = client.instalment_schedules.create_with_dates(
    params={
        'name':         'Invoice #1234',
        'currency':     'GBP',
        'total_amount': 2500,
        'instalments': [
            {'amount': 1500, 'charge_date': '2024-11-01'},
            {'amount': 1000, 'charge_date': '2025-02-01'},
        ],
        'links': {
            'mandate': 'MD123',
        },
    }
)
```

```ruby
require 'gocardless_pro'

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

response = client.instalment_schedules.create_with_dates(
  params: {
    name:         'Invoice #1234',
    currency:     'GBP',
    total_amount: 2500,
    instalments: [
      { amount: 1500, charge_date: '2024-11-01' },
      { amount: 1000, charge_date: '2025-02-01' },
    ],
    links: {
      mandate: 'MD123'
    }
  }
)
```

```java
import com.gocardless.GoCardlessClient;

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

InstalmentSchedule instalmentSchedule = client.instalmentSchedules()
    .createWithDates()
    .withName("Invoice #1234")
    .withCurrency("GBP")
    .withTotalAmount(2500)
    .withInstalment(1500, "2024-11-01")
    .withInstalment(1000, "2025-02-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 instalmentSchedule = await client.instalmentSchedules.createWithDates({
  name: "Invoice #1234",
  currency: "GBP",
  total_amount: 2500,
  instalments: [
    { amount: 1500, charge_date: "2024-11-01" },
    { amount: 1000, charge_date: "2025-02-01" },
  ],
  links: {
    mandate: "MD123",
  },
});
```

```.net
using GoCardless;

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

var instalmentSchedule = await client.InstalmentSchedules.CreateWithDatesAsync(
    new InstalmentScheduleCreateWithDatesRequest
    {
        Name        = "Invoice #1234",
        Currency    = "GBP",
        TotalAmount = 2500,
        Instalments = new List<InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleInstalments>
        {
            new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleInstalments
            {
                Amount     = 1500,
                ChargeDate = "2024-11-01"
            },
            new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleInstalments
            {
                Amount     = 1000,
                ChargeDate = "2025-02-01"
            }
        },
        Links = new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleLinks
        {
            Mandate = "MD123"
        }
    }
);
```

```go
package main

import (
    "context"
    "fmt"
    "os"

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

func main() {
    opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint)
    client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts)
    if err != nil {
        panic(err)
    }

    params := gocardless.InstalmentScheduleCreateWithDatesParams{
        Name:        "Invoice #1234",
        Currency:    "GBP",
        TotalAmount: 2500,
        Instalments: []gocardless.InstalmentScheduleCreateWithDatesParamsInstalments{
            {Amount: 1500, ChargeDate: "2024-11-01"},
            {Amount: 1000, ChargeDate: "2025-02-01"},
        },
        Links: gocardless.InstalmentScheduleCreateWithDatesParamsLinks{
            Mandate: "MD123",
        },
    }

    instalmentSchedule, err := client.InstalmentSchedules.CreateWithDates(context.TODO(), params)
    if err != nil {
        panic(err)
    }
    fmt.Println(instalmentSchedule)
}
```

**Option B** - Create the instalment plan with regular intervals (GoCardless calculates the dates):

```http
curl -X POST https://api.gocardless.com/instalment_schedules \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "instalment_schedules": {
      "name": "Invoice #1234",
      "currency": "GBP",
      "total_amount": 2500,
      "instalments": {
        "start_date": "2024-11-01",
        "interval_unit": "monthly",
        "interval": 1,
        "amounts": [1500, 1000]
      },
      "links": {
        "mandate": "MD123"
      }
    }
  }'
```

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

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

$response = $client->instalmentSchedules()->createWithSchedule([
    'params' => [
        'name'         => 'Invoice #1234',
        'currency'     => 'GBP',
        'total_amount' => 2500,
        'instalments'  => [
            'start_date'    => '2024-11-01',
            'interval_unit' => 'monthly',
            'interval'      => 1,
            'amounts'       => [1500, 1000],
        ],
        'links' => [
            'mandate' => 'MD123',
        ],
    ],
]);
```

```python
import os
import gocardless_pro

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

response = client.instalment_schedules.create_with_schedule(
    params={
        'name':         'Invoice #1234',
        'currency':     'GBP',
        'total_amount': 2500,
        'instalments': {
            'start_date':    '2024-11-01',
            'interval_unit': 'monthly',
            'interval':      1,
            'amounts':       [1500, 1000],
        },
        'links': {
            'mandate': 'MD123',
        },
    }
)
```

```ruby
require 'gocardless_pro'

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

response = client.instalment_schedules.create_with_schedule(
  params: {
    name:         'Invoice #1234',
    currency:     'GBP',
    total_amount: 2500,
    instalments: {
      start_date:    '2024-11-01',
      interval_unit: 'monthly',
      interval:      1,
      amounts:       [1500, 1000]
    },
    links: {
      mandate: 'MD123'
    }
  }
)
```

```java
import com.gocardless.GoCardlessClient;

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

InstalmentSchedule instalmentSchedule = client.instalmentSchedules()
    .createWithSchedule()
    .withName("Invoice #1234")
    .withCurrency("GBP")
    .withTotalAmount(2500)
    .withInstalmentsStartDate("2024-11-01")
    .withInstalmentsIntervalUnit("monthly")
    .withInstalmentsInterval(1)
    .withInstalmentsAmounts(Arrays.asList(1500, 1000))
    .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 instalmentSchedule = await client.instalmentSchedules.createWithSchedule({
  name: "Invoice #1234",
  currency: "GBP",
  total_amount: 2500,
  instalments: {
    start_date: "2024-11-01",
    interval_unit: "monthly",
    interval: 1,
    amounts: [1500, 1000],
  },
  links: {
    mandate: "MD123",
  },
});
```

```.net
using GoCardless;

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

var instalmentSchedule = await client.InstalmentSchedules.CreateWithScheduleAsync(
    new InstalmentScheduleCreateWithScheduleRequest
    {
        Name        = "Invoice #1234",
        Currency    = "GBP",
        TotalAmount = 2500,
        Instalments = new InstalmentScheduleCreateWithScheduleRequest.InstalmentScheduleInstalments
        {
            StartDate    = "2024-11-01",
            IntervalUnit = InstalmentScheduleCreateWithScheduleRequest.InstalmentScheduleInstalments.InstalmentScheduleInstalmentsIntervalUnit.Monthly,
            Interval     = 1,
            Amounts      = new List<int> { 1500, 1000 }
        },
        Links = new InstalmentScheduleCreateWithScheduleRequest.InstalmentScheduleLinks
        {
            Mandate = "MD123"
        }
    }
);
```

```go
package main

import (
    "context"
    "fmt"
    "os"

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

func main() {
    opts := gocardless.WithEndpoint(gocardless.SandboxEndpoint)
    client, err := gocardless.New(os.Getenv("GC_ACCESS_TOKEN"), opts)
    if err != nil {
        panic(err)
    }

    params := gocardless.InstalmentScheduleCreateWithScheduleParams{
        Name:        "Invoice #1234",
        Currency:    "GBP",
        TotalAmount: 2500,
        Instalments: gocardless.InstalmentScheduleCreateWithScheduleParamsInstalments{
            StartDate:    "2024-11-01",
            IntervalUnit: "monthly",
            Interval:     1,
            Amounts:      []int{1500, 1000},
        },
        Links: gocardless.InstalmentScheduleCreateWithScheduleParamsLinks{
            Mandate: "MD123",
        },
    }

    instalmentSchedule, err := client.InstalmentSchedules.CreateWithSchedule(context.TODO(), params)
    if err != nil {
        panic(err)
    }
    fmt.Println(instalmentSchedule)
}
```

**Response:**

```json
{
  "instalment_schedules": {
    "id": "IS123",
    "status": "active",
    "name": "Invoice #1234",
    "currency": "GBP",
    "total_amount": 2500,
    "links": {
      "mandate": "MD123",
      "payments": ["PM001", "PM002"]
    }
  }
```

### Manage the instalment plan

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

| **Event**                      | **Meaning**                               |
| ------------------------------ | ----------------------------------------- |
| instalment_schedules_created   | Schedule created, all payments queued     |
| payments_confirmed             | Individual payment collected successfully |
| payments_failed                | Individual payment failed                 |
| instalment_schedules_completed | All payments in the schedule collected    |
| instalment_schedules_errored   | One or more payments failed               |

You can cancel the instalment plan:

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

```php
$response = $client->instalmentSchedules()->cancel('IS123');
```

```python
response = client.instalment_schedules.cancel('IS123')
```

```ruby
response = client.instalment_schedules.cancel('IS123')
```

```java
InstalmentSchedule instalmentSchedule = client.instalmentSchedules()
    .cancel("IS123")
    .execute();

```

```javascript
const instalmentSchedule = await client.instalmentSchedules.cancel("IS123");
```

```.net
var instalmentSchedule = await client.InstalmentSchedules.CancelAsync("IS123");
```

```go
instalmentSchedule, err := client.InstalmentSchedules.Cancel(context.TODO(), "IS123", gocardless.InstalmentScheduleCancelParams{})
```
