# Payment Types

> Shuttle supports four payment models. All of them create a contract under the hood — the differences are in how and when charges are generated and when payment

Shuttle supports four payment models. All of them create a contract under the hood — the differences are in how and when charges are generated and when payment is attempted. Any model other than single pay-now relies on the [scheduler](/platforms/user-guides/scheduler/) to drive future-dated activity.

If contracts and charges are new to you, read [Core concepts](/platforms/user-guides/concepts/) first. What Shuttle accepts and refuses when creating each of these is in [Take a one-off payment](/platforms/user-guides/rules-payment-take/) and [Set up a recurring or scheduled agreement](/platforms/user-guides/rules-contract-create/).

<br />

| Model | How charges are created | When payment is attempted | Amounts | Typical use case |
|---|---|---|---|---|
| **Single pay-now** | One charge at creation | Immediately (synchronous) | Fixed | One-off purchase |
| **Scheduled one-time** | One charge at creation | Asynchronously on the scheduled date | Fixed | A single payment agreed now, taken on a specific future date (e.g., end-of-month billing) |
| **Recurring (frequency-based)** | One charge per billing cycle, generated as each cycle becomes due | Asynchronously shortly after each charge is created | Same each cycle | Subscriptions, memberships |
| **Scheduled charges** | All charges created upfront from an explicit array | Sync for any charge due now/in the past; async for future-dated charges | Vary per charge | Irregular instalment plans, staged billing |

## Single Pay-Now

A one-off payment taken immediately.

**Required:** `currency`, `amount`, `payment_method`, `account`
**Omit:** `frequency` (or set to `ONEOFF`), `scheduled_date`, `charges`

```json
{
  "payment": {
    "currency": "GBP",
    "amount": "49.99",
    "account": { "crm_key": "CUS-001" },
    "payment_method": { "card_number": "4111...", "card_cvc": "123", "card_expiry": "2030-12" }
  }
}
```

## Scheduled One-Time Payment

A single payment deferred to a future date.

**Key fields:** `scheduled_date` (ISO timestamp, up to 365 days out) **or** `scheduled_days` (integer, up to 31).

The charge is created at the moment of contract creation, with its due date set to `scheduled_date`. The [scheduler](/platforms/user-guides/scheduler/) picks it up and attempts payment when that time arrives (typically within a few minutes of the scheduled time). A failed attempt enters the normal retry flow.

```json
{
  "payment": {
    "currency": "GBP",
    "amount": "200.00",
    "scheduled_date": "2026-06-01T09:00:00Z",
    "account": { "crm_key": "CUS-001" },
    "payment_method": "pm_11842_10000"
  }
}
```

## Recurring (Frequency-Based) Payment

A series of charges generated on a regular cadence. Charges are **created one at a time** — when a charge becomes due, it is created, the frequency is applied to determine the next `next_charge` date, and payment is attempted asynchronously against the newly-created charge (typically within a minute of the charge being created). Failed payments are retried automatically — see [Scheduler](/platforms/user-guides/scheduler/) for the retry schedules.

**Key fields:** `frequency`, `occurrences` (blank = forever), `start_date` or `start_days`.

**`frequency` enum:** `ONEOFF`, `WEEKLY`, `FORTNIGHTLY`, `BIMONTHLY`, `MONTHLY`, `QUARTERLY`, `BIANNUALLY`, `ANNUALLY`.

### Frequency Specifics

* **BIMONTHLY** — charges fall on the 1st and the 15th of every month.
* **MONTHLY, QUARTERLY, BIANNUALLY, ANNUALLY** — calculated from the previous charge date. When the previous charge date does not exist in the target month, the charge falls on the last day of that month and **subsequent** charges are calculated from that adjusted date rather than the original anchor. For example, a monthly contract whose first charge is on **31 January** produces the next charge on **28 February** (or 29 Feb in a leap year), then **28 March**, **28 April**, and so on — the anchor drifts to 28th and stays there.

```json
{
  "payment": {
    "currency": "GBP",
    "amount": "19.99",
    "frequency": "MONTHLY",
    "occurrences": 12,
    "start_date": "2026-05-01T00:00:00Z",
    "account": { "crm_key": "CUS-001" },
    "payment_method": "pm_11842_10000"
  }
}
```

## Scheduled Charges

An explicit list of charges, each with its own amount and due date. All charges are created upfront at contract creation. Use this when amounts or dates vary between charges — e.g., irregular instalment plans, staged billing for services, or deposits followed by balance payments.

**Key field:** `charges[]`. Each entry accepts:

| Field | Required | Description |
|---|---|---|
| `alt_key` | No | Your reference for the charge (e.g., instalment number or invoice line ID) |
| `amount` | Yes | The charge amount, as a string |
| `due` | Yes | ISO 8601 timestamp or the literal string `"now"`. A timestamp more than 24 hours in the past is rejected |

**When each charge is taken:**

| `due` value | Timing | Effect of a decline |
|---|---|---|
| `"now"` or a past timestamp (within 24h) | Taken synchronously during contract creation | Blocks contract creation — no contract is created |
| Future timestamp | Taken asynchronously by the scheduler on the due date | Contract is created regardless; the charge enters the normal retry flow |

To have the first charge run asynchronously, set its `due` to a future timestamp (even a few minutes ahead).

**Rules:**

* Cannot be combined with `frequency` (must be omitted or `ONEOFF`)
* Not supported with `action: AUTH`
* The top-level `amount` is optional. If provided, it must equal the sum of `charges[].amount`

```json
{
  "payment": {
    "currency": "GBP",
    "account": { "crm_key": "CUS-001" },
    "payment_method": "pm_11842_10000",
    "charges": [
      { "alt_key": "DEPOSIT",    "amount": "100.00", "due": "now" },
      { "alt_key": "BALANCE_1",  "amount": "50.00",  "due": "2026-06-01T09:00:00Z" },
      { "alt_key": "BALANCE_2",  "amount": "50.00",  "due": "2026-07-01T09:00:00Z" }
    ]
  }
}
```

Retrieve the resulting charges via [List contract charges](/platforms/reference/operations/listcontractcharges/). Each entry on a scheduled-charges contract is a normal charge object and can be listed, retrieved, or modified via the standard [Charges API](/platforms/reference/operations/tags/charges/).

## Choosing Between Recurring and Scheduled Charges

| If… | Use |
|---|---|
| Amount and cadence are uniform (e.g., £20 every month) | Recurring |
| You want "forever until cancelled" billing | Recurring |
| Amounts or dates vary between charges | Scheduled charges |
| You have a finite, pre-known schedule (e.g., deposit + 3 instalments on specific dates) | Scheduled charges |
| You need per-charge references (`alt_key`) for reconciliation | Scheduled charges |

## Converting a Recurring Contract to Scheduled Charges

If you need to change a specific future instalment on a recurring contract — a different amount, a different date, an extra one-off charge — you can convert the contract to scheduled charges mid-stream. This switches the contract from frequency-based generation to an explicit list of remaining charges that you can then manage individually.

**Prerequisite:** the recurring contract must have a finite `occurrences` value. Scheduled-charges contracts are finite by definition, so a "forever until cancelled" recurring contract cannot be converted.

**Process:**

1. Fetch the existing charges on the contract via [`GET /contracts/{id}/charges`](/platforms/reference/operations/listcontractcharges/).
2. Send a [`PUT /contracts/{id}`](/platforms/reference/operations/updatecontract/) with a `charges[]` array that contains **every existing charge** — even ones that have already been paid or written off — plus any modifications, deletions, or additions you want.

**Rule for past charges.** Any charge that has already been processed (`COMPLETED`, `WRITTENOFF`, or `PENDING`) must appear in the array with **just its `id` or `alt_key` and no other fields**. Listing them is purely about acknowledging the current state of the existing contract — these charges stay on the cancelled original as historical record and are **not** recreated on the new contract. Omitting a charge is interpreted as a request to remove it; past charges will refuse the deletion and the request will fail.

**Rule for unpaid future charges.** Unpaid charges from the existing contract are transferred across to the new contract. You can:

* Leave unchanged: `{ "id": "cg_..." }`
* Modify: `{ "id": "cg_...", "amount": "25.00" }` (only the fields you want to change)
* Delete: `{ "id": "cg_...", "delete": true }`
* Add a new one: `{ "alt_key": "BONUS", "amount": "15.00", "due": "2026-09-15T09:00:00Z" }`

In any of these, you can identify an existing charge by `id` or `alt_key` interchangeably.

**Example — modify a future instalment, delete another, add a new one:**

```json
PUT /contracts/co_11842_10000
{
  "contract": {
    "charges": [
      { "id": "cg_11842_10001" },
      { "id": "cg_11842_10002" },
      { "id": "cg_11842_10003", "amount": "25.00" },
      { "id": "cg_11842_10004", "delete": true },
      { "alt_key": "BONUS", "amount": "15.00", "due": "2026-09-15T09:00:00Z" }
    ]
  }
}
```

In this example, charges `10001` and `10002` are preserved unchanged (already paid), `10003` is updated to a new amount, `10004` is removed, and a new charge is appended at the end. After the update the contract behaves as a scheduled-charges contract — it will no longer generate further charges by frequency, and you manage it by amending `charges[]` rather than `frequency` / `occurrences`.

The conversion is one-way: once converted, you can't switch back to frequency-based generation on the same contract.

## Related

* [Scheduler](/platforms/user-guides/scheduler/) — how deferred charges are processed, retry schedules, and the `next_charge` / `next_payment` fields