---
title: Settlements
description: Pay your wallet balance out to your own accounts, on a schedule or on demand.
---

A settlement pays your wallet balance out to your business's own mobile money or bank account. You choose where it goes, how often it runs and the smallest amount worth sending. You can also settle now.

## Before you start

Settlements only go to accounts an owner has verified in the [developer console](https://console.example.com). A key cannot add an account or name one. It can only choose between the accounts already verified.

## Read your settlement policy

```http
GET /v1/settlement-policy
```

```json
{
  "options": {
    "momo": { "available": true },
    "bank": { "available": false, "reason": "Bank settlement is not available yet." },
    "split": { "available": false, "reason": "Bank settlement is not available yet." }
  },
  "policy": {
    "destination": "momo",
    "legs": [
      { "accountType": "momo", "label": "MTN •••• 3456", "sharePercent": 100 }
    ],
    "schedule": { "mode": "scheduled", "frequency": "daily", "timeOfDay": "17:00", "timezone": "Africa/Accra" },
    "minimum": "50.00",
    "currency": "GHS",
    "version": 3,
    "inSync": true
  }
}
```

The values above only show the shape.

- `options` says which destinations you can choose right now, and `reason` says why one is not.
- `policy` is `null` when settlement is off.
- Each leg shows the account masked to its last four digits.
- `version` goes up each time the policy changes.
- `inSync` is `false` when the policy no longer matches a verified account. See [Shared with the merchant console](#shared-with-the-merchant-console).

## Set your settlement policy

```http
PUT /v1/settlement-policy
Idempotency-Key: policy-2026-10-05
```

```json
{
  "destination": "momo",
  "schedule": { "mode": "scheduled", "frequency": "weekly", "weekday": 5, "timeOfDay": "17:00" },
  "minimum": "50.00"
}
```

A `200` returns the saved policy, in the same shape as the read.

### Destination

| `destination` | Where the money goes                                                    |
| ------------- | ----------------------------------------------------------------------- |
| `momo`        | The verified mobile money account.                                      |
| `bank`        | The verified bank account.                                              |
| `split`       | Both. `bankSharePercent` (1 to 99) is the share sent to the bank.       |

Bank and split may not be available yet. Check `options` first. Choosing one that is not available is refused with `422 bank_settlement_unavailable`.

### Schedule

| Field        | Value                                                                  |
| ------------ | ---------------------------------------------------------------------- |
| `mode`       | `scheduled`, or `on_demand_only` to settle only when you ask.          |
| `frequency`  | `daily`, `weekly` or `monthly`, for `scheduled`.                       |
| `timeOfDay`  | 24-hour time, such as `"17:00"`.                                       |
| `weekday`    | For weekly. `0` is Sunday, `6` is Saturday.                            |
| `dayOfMonth` | For monthly. `1` to `28`.                                              |

Times are in Africa/Accra. A `timezone` you send is ignored.

### Minimum

`minimum` is a decimal string in GHS. Settlements smaller than it wait. Send an empty string for no minimum.

## Turn settlement off

```http
DELETE /v1/settlement-policy
Idempotency-Key: policy-off-2026-10-05
```

A `204` means settlement is off, and your balance stays in your wallet. Repeating it is safe.

## Shared with the merchant console

If your business also uses the iSmartPay merchant console, both share one settlement policy. A change made there replaces yours, and a change made here replaces theirs.

The two consoles keep their settlement accounts apart, so an owner verifies the accounts in each. When the policy points at an account not verified in the developer console, `inSync` is `false`. Read the policy before you rely on it, and save it again if it is not what you expect.

## Settle now

```http
POST /v1/settlements
Idempotency-Key: settle-2026-10-05-1
```

```json
{ "reference": "settle-2026-10-05-1" }
```

- `reference` is yours: 1 to 64 letters, digits, underscores or hyphens, starting with a letter or digit.
- The run pays out as your policy says, without waiting for the schedule.

A `202` means the run started:

```json
{
  "id": "3c9e1a52-7b4d-4f8e-a1c6-2d5b9e0f7a13",
  "reference": "settle-2026-10-05-1",
  "status": "running",
  "itemCount": 1,
  "total": "1250.50",
  "currency": "GHS",
  "startedAt": "2026-10-05T10:00:00Z"
}
```

Keep the `id`. You read the run back with it. With no settlement policy, settle now is `404`.

If a request times out or returns `5xx`, retry with the same `Idempotency-Key` and body.

## Runs

| Field         | Meaning                                                                    |
| ------------- | -------------------------------------------------------------------------- |
| `status`      | `running` or `completed`.                                                  |
| `outcome`     | Set once `completed`: `settled`, `failed_partial` or `failed_all`.         |
| `itemCount`   | How many payments the run made.                                            |
| `total`       | The amount settled.                                                        |
| `completedAt` | When the run finished.                                                     |

Other statuses and outcomes can appear, so do not treat these lists as closed.

Read runs with:

- `GET /v1/settlements/{id}` for one run. Another business's run is `404`.
- `GET /v1/settlements/latest` for the newest run. It returns `{"run": null}` when there has been none.
- `GET /v1/settlements` for all runs, scheduled and on demand, newest first. `limit` is 1 to 50 and defaults to 20. Pass `nextCursor` as `cursor` for the next page. It is absent on the last page.

## Retry a failed run

When a `completed` run has `outcome` `failed_partial` or `failed_all`, you can pay the failed part again:

```http
POST /v1/settlements/3c9e1a52-7b4d-4f8e-a1c6-2d5b9e0f7a13/resettlements
Idempotency-Key: resettle-2026-10-05-1
```

```json
{ "reference": "resettle-2026-10-05-1" }
```

- The retry uses your current policy.
- A `202` returns the new run. The original run is kept.
- A run can be retried once. A second retry is `409 settlement_already_retried`.
- Any other run is `409 resettlement_not_allowed`.

## Permissions

| To                                   | The key needs               |
| ------------------------------------ | --------------------------- |
| Read the settlement policy           | `settlement_policies.read`  |
| Set the policy or turn it off        | `settlement_policies.write` |
| Settle now or retry a run            | `settlements.write`         |
| Read runs                            | `settlements.read`          |

## Webhooks

Subscribe an endpoint to this event in the console:

| Type                        | Sent when                                                         |
| --------------------------- | ----------------------------------------------------------------- |
| `settlement.status_changed` | A run starts or finishes, scheduled or started by you.            |

`data` is the run as it stood when the event was sent. It has no `id`. To find the run, list runs with `GET /v1/settlements` and match on `reference`.

On a `completed` run, check `outcome`. You can retry `failed_partial` and `failed_all`.

If your webhook endpoints were set up before settlements arrived, edit or add an endpoint in the console once. Until then, settlement events are not sent to your business. See [Webhooks](/guides/webhooks).

## Errors

As well as the [common errors](/guides/errors):

| Status | Code                          | What to do                                                       |
| ------ | ----------------------------- | ---------------------------------------------------------------- |
| 400    | `invalid_input`               | A field is missing or malformed. Read `message`.                 |
| 409    | `settlement_in_progress`      | A run is already going. Wait for it to finish.                   |
| 409    | `resettlement_not_allowed`    | Only a `completed` run with `failed_partial` or `failed_all` can be retried. |
| 409    | `settlement_already_retried`  | This run was retried before. Follow that run instead.            |
| 422    | `account_not_verified`        | The destination has no verified account. An owner verifies it in the console. |
| 422    | `bank_settlement_unavailable` | Bank and split are not available yet. Choose `momo`.             |
| 422    | `destination_not_verified`    | When you save a policy, the provider is asked who holds each new or changed destination. It could not confirm this one. Nothing changed. Check the account in the console, then save again. |
| 503    | `destination_verification_unavailable` | The provider could not be reached for that check. Nothing changed. Save again shortly. |
| 422    | `policy_missing_provider`, `policy_not_nettable` | The policy cannot be paid out as it stands. Save it again, then retry. |
