---
title: Transactions and events
description: List what moved through your wallet, and catch up on webhooks you missed.
---

Two feeds help you reconcile. `GET /v1/transactions` lists money in and out of your wallet. `GET /v1/events` replays the events sent to your webhooks.

## Transactions

```http
GET /v1/transactions?kind=wallet_transfer&from=2026-10-01T00:00:00Z&limit=50
```

```json
{
  "items": [
    {
      "id": "txn_8d2f4a1c",
      "kind": "wallet_transfer",
      "direction": "in",
      "reference": "supplier-7731",
      "amount": "25.00",
      "currency": "GHS",
      "status": "completed",
      "createdAt": "2026-10-05T10:00:00Z"
    }
  ],
  "nextCursor": "eyJvIjo1MH0"
}
```

The values above only show the shape.

Items come newest first. Each has the same fields as a collection, plus:

| Field       | Meaning                                                              |
| ----------- | -------------------------------------------------------------------- |
| `id`        | The platform's ID for this transaction. Quote it to support.         |
| `kind`      | `collection`, `payout`, `settlement`, `utility` or `wallet_transfer`. |
| `direction` | `in` for money received, `out` for money sent.                       |
| `completedAt` | When it reached its final status. Absent while it is in progress, and on older payments whose finish time was not recorded. |
| `channel`   | How the instruction arrived. Always `api` today.                     |
| `settlementStatus` | Collections only: `not_eligible`, `eligible`, `claimed` or `settled`. Where the money stands with settlement. |
| `reconciliation` | `{status, checkedAt}`. `status` is `unchecked`, `matched` or `mismatched`: whether the provider's records agree with ours. |
| `parent`, `compensation` | `{type, reference}` links between a reversal and the payment it undoes. Absent when there is none. |

`reference` is the one you chose. On a scheduled settlement, the platform chose it. On a transfer you received, the sending business chose it.

### Filters

| Parameter | Meaning                                                    |
| --------- | ---------------------------------------------------------- |
| `kind`    | Only this kind.                                            |
| `status`  | Only this status.                                          |
| `channel` | Only this channel. Collections and payouts only.           |
| `settlementStatus` | Only collections in this settlement state.        |
| `reconciliationStatus` | Only collections and payouts in this reconciliation state. |
| `from`    | Only transactions created at or after this time.           |
| `to`      | Only transactions created before this time.                |
| `limit`   | 1 to 100. Defaults to 50.                                  |
| `cursor`  | The `nextCursor` of the previous page.                     |

### Short pages

A page can hold fewer items than `limit` before the end. Keep calling with `nextCursor` until it is absent. Do not stop at the first short page.

## Missed events

If your endpoint was down, `GET /v1/events` gives you every event sent to your webhooks since a point you choose. Each item is the event exactly as it was delivered.

```http
GET /v1/events?after=evt_3f2a9c0d8e7b4a1f9c2d6e5b4a3f2e1d&limit=50
```

```json
{
  "items": [
    {
      "id": "evt_9b1e7c3a2d4f4e6a8c0b1d2e3f4a5b6c",
      "type": "payout.status_changed",
      "createdAt": "2026-10-05T10:02:11Z",
      "data": { "reference": "payroll-2026-10-001", "status": "delivered" }
    }
  ],
  "nextAfter": "evt_9b1e7c3a2d4f4e6a8c0b1d2e3f4a5b6c"
}
```

- `after` is the `id` of the last event you processed. Leave it out to start from the first event. An ID that is not one of your events is refused.
- Events are kept for 90 days. An `after` older than that is refused too, so start again without it and skip the events you have already handled.
- `limit` is 1 to 200. It defaults to 50.
- Keep calling with `nextAfter` until it is absent. Later, resume from the `id` of the last item you processed.

### Order

Events come in the order iSmartPay stored them, not by `createdAt`. An event that arrived late comes after the ones before it, even if its `createdAt` is earlier. So `after` never skips it.

An event shows up here about 5 seconds after it is stored. A call made right after a webhook may not include that event yet.

### What you see

A key sees only the event types its permissions cover:

| Events                              | The key needs          |
| ----------------------------------- | ---------------------- |
| `collection.*`                      | `collections.read`     |
| `payout.*`, `utility_purchase.*`    | `disbursements.read`   |
| `settlement.status_changed`         | `settlements.read`     |
| `transfer.status_changed`, `transfer.received` | `wallettransfer.read` |

Events only exist once your business has a webhook endpoint. Utility purchase, settlement and transfer events start after an endpoint is created or edited in the console.

Use the same duplicate check as for webhooks. An event you already handled from a delivery has the same `id` here. See [Webhooks](/guides/webhooks).

## Permissions

| To                   | The key needs                                                                       |
| -------------------- | ----------------------------------------------------------------------------------- |
| List transactions    | `transactions.read`                                                                 |
| List events          | Any of `collections.read`, `disbursements.read`, `settlements.read`, `wallettransfer.read` |

## Errors

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

| Status | Code            | What to do                                                            |
| ------ | --------------- | --------------------------------------------------------------------- |
| 400    | `invalid_input` | A parameter is malformed, or `after` is not one of your events or is older than 90 days. Read `message`. |
