# Instalment Schedules

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

# 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.

- 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 '
    }
  }'
```

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

### 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 ',
        
      ],
      "links": 
    }
  }'
```

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

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

response = client.instalment_schedules.create_with_dates(
    params=,
            ,
        ],
        'links': ,
    }
)
```

```ruby
require 'gocardless_pro'

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

response = client.instalment_schedules.create_with_dates(
  params: ,
      ,
    ],
    links: 
  }
)
```

```java

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(,
    ,
  ],
  links: ,
});
```

```cs
using GoCardless;

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

var instalmentSchedule = await client.InstalmentSchedules.CreateWithDatesAsync(
    new InstalmentScheduleCreateWithDatesRequest
    ,
            new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleInstalments
            
        },
        Links = new InstalmentScheduleCreateWithDatesRequest.InstalmentScheduleLinks
        
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

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

func main() 

    params := gocardless.InstalmentScheduleCreateWithDatesParams,
            ,
        },
        Links: gocardless.InstalmentScheduleCreateWithDatesParamsLinks,
    }

    instalmentSchedule, err := client.InstalmentSchedules.CreateWithDates(context.TODO(), params)
    if err != nil 
    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 ',
      "links": 
    }
  }'
```

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

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

response = client.instalment_schedules.create_with_schedule(
    params=,
        'links': ,
    }
)
```

```ruby
require 'gocardless_pro'

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

response = client.instalment_schedules.create_with_schedule(
  params: ,
    links: 
  }
)
```

```java

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

```cs
using GoCardless;

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

var instalmentSchedule = await client.InstalmentSchedules.CreateWithScheduleAsync(
    new InstalmentScheduleCreateWithScheduleRequest
    
        },
        Links = new InstalmentScheduleCreateWithScheduleRequest.InstalmentScheduleLinks
        
    }
);
```

```go
package main

    "context"
    "fmt"
    "os"

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

func main() 

    params := gocardless.InstalmentScheduleCreateWithScheduleParams,
        },
        Links: gocardless.InstalmentScheduleCreateWithScheduleParamsLinks,
    }

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

**Response:**

```json

  }
}
```

### 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");
```

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

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

## What's next?

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

Create mandates and collect bank account details via the API.

  
#### [Subscriptions](/docs/collect-payments/recurring-payments/subscriptions)

Collect a fixed amount on a regular schedule against an active mandate.

  
#### [Instalment Schedule Events](/docs/api-reference/events/instalment-schedules)

Understand the webhook events fired during instalment schedule lifecycle.

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

Automatically retry failed instalment payments.