> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peerpesa.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction History and Status Tracking

> Query onramp and offramp transactions with filters and page-number pagination, retrieve a single transaction by ID, and understand the status lifecycle.

Every conversion you create through PeerPesa is tracked as a transaction. You can list transactions to reconcile activity, filter by status or date, and retrieve a single transaction for full details including fees, rates, and blockchain confirmation data.

<Note>
  All endpoints require a valid Bearer token. See [Authentication](/authentication) for how to obtain one.
</Note>

## List transactions

Retrieve a paginated list of transactions with optional filters.

### Endpoint

`GET /transactions`

### Query parameters

<ParamField query="type" type="string">
  Filter by transaction type: `onramp`, `offramp`, `deposit`, `withdraw`, `send`, `buy`, or `swap`.
</ParamField>

<ParamField query="recurring_payment_id" type="string">
  Only return transactions created by this [recurring payment](/api-reference/recurring-payments), for example `rp_5t8w2k`.
</ParamField>

<ParamField query="status" type="string">
  Filter by status: `awaiting_payment`, `awaiting_deposit`, `processing`, `completed`, `failed`, `expired`, or `refunded`.
</ParamField>

<ParamField query="network" type="string">
  Filter by blockchain network, for example `stellar` or `celo`.
</ParamField>

<ParamField query="search" type="string">
  Matches transaction ID, `order_id`, `reference`, wallet addresses, `tx_hash`, and account numbers. Minimum 2 characters.
</ParamField>

<ParamField query="start_date" type="string">
  Only include transactions created on or after this date (`YYYY-MM-DD` or ISO 8601, UTC).
</ParamField>

<ParamField query="end_date" type="string">
  Only include transactions created on or before this date (`YYYY-MM-DD` or ISO 8601, UTC).
</ParamField>

<ParamField query="currency" type="string">
  Filter by asset or fiat currency, for example `USDC` or `KES`.
</ParamField>

<ParamField query="min_amount" type="number">
  Only include transactions with an amount greater than or equal to this value.
</ParamField>

<ParamField query="max_amount" type="number">
  Only include transactions with an amount less than or equal to this value.
</ParamField>

<ParamField query="sort_by" default="created_at" type="string">
  `created_at`, `updated_at`, or `amount`.
</ParamField>

<ParamField query="sort_order" default="desc" type="string">
  `desc` or `asc`.
</ParamField>

<ParamField query="page" default="1" type="integer">
  Page number to return, starting at `1`. See [Pagination and filters](/pagination).
</ParamField>

<ParamField query="size" default="20" type="integer">
  Number of results per page. Maximum is `100`.
</ParamField>

<ParamField query="limit" default="20" type="integer">
  Alias for `size`. If you send both, `size` is used.
</ParamField>

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.peerpesa.co/v1/transactions?page=1&size=20&status=completed&start_date=2026-07-01&end_date=2026-07-31" \
    -H "Authorization: Bearer <access_token>"
  ```

  ```javascript JavaScript theme={null}
  fetch('https://api.peerpesa.co/v1/transactions?page=1&size=20&status=completed&start_date=2026-07-01&end_date=2026-07-31', {
    method: 'GET',
    headers: {
      Authorization: 'Bearer <access_token>',
    },
  })
    .then((res) => res.json())
    .then((data) => console.log(data));
  ```
</CodeGroup>

### Example response

```json theme={null}
{
  "data": [
    {
      "id": "txn_3j9x2kL8pQvW",
      "type": "offramp",
      "status": "completed",
      "quote_id": "qt_8f2k9mN4pQrS",
      "network": "stellar",
      "asset": "USDC",
      "fiat_currency": "KES",
      "source_amount": "100.00",
      "destination_amount": "12945.00",
      "fee": {
        "total": "1.50",
        "currency": "USDC",
        "processing_fee": "1.00",
        "network_fee": "0.50"
      },
      "rate": "129.45",
      "tx_hash": "a1b2c3d4e5f6...",
      "beneficiary_id": "ben_2k9mN4pQrS7T",
      "reference": "order-98765",
      "created_at": "2024-06-10T14:23:00Z",
      "updated_at": "2024-06-10T14:35:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "size": 20,
    "total": 134,
    "total_pages": 7
  }
}
```

### Response fields

<ResponseField name="data" type="array">
  List of transaction objects.
</ResponseField>

<ResponseField name="data[].id" type="string">
  Unique transaction identifier starting with `txn_`.
</ResponseField>

<ResponseField name="data[].type" type="string">
  Transaction type: `onramp`, `offramp`, `deposit`, `withdraw`, `send`, `buy`, or `swap`. See the [wallet operations](/api-reference/balances) pages for wallet transaction types.
</ResponseField>

<ResponseField name="data[].status" type="string">
  Current status in the transaction lifecycle.
</ResponseField>

<ResponseField name="data[].source_amount" type="string">
  Amount being converted, as a decimal string.
</ResponseField>

<ResponseField name="data[].destination_amount" type="string">
  Amount the recipient receives after fees, as a decimal string.
</ResponseField>

<ResponseField name="data[].fee" type="object">
  Fee breakdown including `total`, `currency`, `processing_fee`, and `network_fee`.
</ResponseField>

<ResponseField name="data[].rate" type="string">
  Exchange rate applied to the transaction.
</ResponseField>

<ResponseField name="data[].tx_hash" type="string | null">
  Blockchain transaction hash when available (null until confirmed).
</ResponseField>

<ResponseField name="pagination" type="object">
  Page details: `page`, `size`, `total` (matching transactions across all pages), and `total_pages`. See [Pagination](/pagination).
</ResponseField>

***

## Retrieve a transaction

Fetch complete details for a single transaction by its ID.

### Endpoint

`GET /transactions/{id}`

### Path parameters

<ParamField path="id" type="string" required>
  The unique transaction ID, for example `txn_3j9x2kL8pQvW`.
</ParamField>

### Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.peerpesa.co/v1/transactions/txn_3j9x2kL8pQvW" \
    -H "Authorization: Bearer <access_token>"
  ```

  ```javascript JavaScript theme={null}
  fetch('https://api.peerpesa.co/v1/transactions/txn_3j9x2kL8pQvW', {
    method: 'GET',
    headers: {
      Authorization: 'Bearer <access_token>',
    },
  })
    .then((res) => res.json())
    .then((data) => console.log(data));
  ```
</CodeGroup>

### Example response

```json theme={null}
{
  "id": "txn_3j9x2kL8pQvW",
  "type": "onramp",
  "status": "awaiting_payment",
  "quote_id": "qt_8f2k9mN4pQrS",
  "network": "celo",
  "asset": "USDC",
  "fiat_currency": "NGN",
  "source_amount": "50000.00",
  "destination_amount": "48.50",
  "fee": {
    "total": "1.50",
    "currency": "USDC",
    "processing_fee": "1.00",
    "network_fee": "0.50"
  },
  "rate": "1030.93",
  "tx_hash": null,
  "wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "reference": "user-deposit-42",
  "created_at": "2024-06-11T09:15:00Z",
  "updated_at": "2024-06-11T09:15:00Z"
}
```

***

## Transaction status lifecycle

Statuses move forward in one direction except for terminal failure states and manual refunds.

| Status | Description |
| - | - |
| `awaiting_payment` | Onramp only. Fiat payment from the user has not yet been received. |
| `awaiting_deposit` | Offramp only. Crypto deposit from the user has not yet been confirmed on chain. |
| `processing` | Funds have been received and the conversion or payout is in progress. |
| `completed` | The conversion finished successfully and the destination funds have been delivered. |
| `failed` | The transaction could not complete. No funds were lost; any received funds are refunded automatically when possible. |
| `expired` | The quote or deposit window expired before funds were received. |
| `refunded` | A refund was issued after a failure or manual request. |

<Warning>
  A transaction can reach `expired` if the quote expires before fiat payment (onramp) or crypto deposit (offramp) is received. Always create a fresh quote if the previous one has expired.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.