---
title: The ledger
description: Every collection, payout and refund is a transaction. How they're typed, how they resolve, and how references keep retries safe.
---

RazPay keeps one ledger per project. Each row is a **transaction**: money in, or money out.

| `type` | `direction` | What it is |
| --- | --- | --- |
| `collection` | `in` | A customer paid you: a payment request, a charge under a pre-approval, or a paid invoice. |
| `payout` | `out` | You sent money from your disbursement account to someone. |
| `refund` | `out` | You returned money for an earlier collection. |

## Lifecycle

Every transaction starts `pending` and ends `successful` or `failed`. It never changes after that.

1. You create it (collect, pay out or refund). RazPay records it as `pending` and sends the instruction to the provider.
2. The provider resolves it. MTN tells RazPay through a callback, and RazPay also checks every pending transaction in the background, so a missed callback never leaves one stuck.
3. RazPay records the result and sends your project a [webhook](/docs/concepts/webhooks).

If the provider rejects the request outright (an unknown number, for example), the API call itself fails and the transaction is recorded as `failed`.

A transaction the provider still can't resolve after **24 hours** is closed as `failed` with the reason `expired: provider returned no terminal status within the reconciliation window`. In practice a customer has about 5 minutes to approve a MoMo prompt.

## References and retries

You give every transaction an `external_reference`: your own order id, payout id or similar. It's unique within your project, **across every type**: a payout can't reuse a collection's reference.

The reference makes every write safe to retry. Sending the same request again with the same `external_reference` returns the original transaction instead of charging or paying twice. If your request times out, retry it with the same reference.

Look any transaction up by its reference with [`GET /payments/{reference}`](/docs/api/get-transaction).

## The transaction object

- **`external_reference`** · `string` · required

  Your reference for this transaction.

- **`type`** · `string` · required

  `collection`, `payout` or `refund`.

- **`direction`** · `string` · required

  `in` for collections, `out` for payouts and refunds.

- **`provider_id`** · `string` · required

  The provider it went through, e.g. `momo`.

- **`provider_ref`** · `string`

  The reference RazPay gave the provider (MoMo's `X-Reference-Id`). Quote it when you contact the provider.

- **`amount`** · `number` · required

  Amount in major units, e.g. `30.00`.

- **`currency`** · `string` · required

  ISO 4217 code, e.g. `SZL`.

- **`status`** · `string` · required

  `pending`, `successful` or `failed`.

- **`financial_tx_id`** · `string`

  The provider's financial transaction id, once successful.

- **`failure_reason`** · `string`

  Why it failed, in plain words. Only when `status` is `failed`. See [Errors](/docs/concepts/errors#failure-reasons).

- **`payer_phone`** · `string`

  The number that paid. Collections only.

- **`payee_phone`** · `string`

  The number that received the money. Payouts and refunds only.

- **`party_name`** · `string`

  The wallet owner's name, when RazPay looked it up (payouts, and refunds of those payments).

- **`description`** · `string`

  The description you sent.

- **`refund_of`** · `string`

  For a refund, the `external_reference` of the collection it returns.

- **`metadata`** · `object` · required

  Your own data, stored and returned exactly as sent. RazPay never reads it.

- **`created_at`** · `integer` · required

  Unix time (seconds) it was created.

- **`updated_at`** · `integer` · required

  Unix time (seconds) of its last change.
