# Get ledger balances and transactions In this tutorial, you'll use two ledger API operations to monitor your account balance and retrieve a detailed record of activity in your prefunded account: 1. **Get available balances** — retrieve the current available and reserved balances for your account. 2. **Get ledger transactions** — retrieve a paginated list of ledger transactions within a date-time range for reconciliation. You'll also learn how to: - Paginate through large result sets using offset-based pagination. - Filter by payment ID to find all ledger entries associated with a specific payment. - Export results as CSV for use in reconciliation workflows. For background on how ledger operations (RESERVE, DEBIT, CREDIT, RELEASE) affect your balance, see [Ledger transactions](/products/payments-direct-2/api-docs/concepts/ledger-transactions). ## Before you begin To follow this tutorial, you need: - Access to the Ripple Payments Direct 2.0 API UAT environment. - A valid OAuth2 access token. See [Request an access token](/products/payments-direct-2/api-docs/tutorials/request-an-access-token). - At least one completed or in-flight payment (to observe meaningful ledger entries). ## Step 1: Get available balances Use the **Get available balances** operation to see how much is currently available in your prefunded account, and how much is reserved for in-flight payments. ### Endpoint `GET /v2/balances` ### Optional query parameter | Parameter | Type | Description | | --- | --- | --- | | `currency` | string | Filter results to a single currency (for example, `USD`). If omitted, all currencies are returned. | ### Example request — all currencies ```bash curl -X GET "https://api.test.ripple.com/v2/balances" \ -H "Authorization: Bearer " ``` ### Example request — USD only ```bash curl -X GET "https://api.test.ripple.com/v2/balances?currency=USD" \ -H "Authorization: Bearer " ``` ### Example response ```json { "timestamp": "2025-03-15T10:30:00.000000Z", "balances": [ { "fundingType": "FUNDED", "currency": "USD", "availableBalance": 50000.00, "reservedBalance": 2500.00 } ] } ``` ### Understanding the balance fields | Field | Description | | --- | --- | | `availableBalance` | Funds that are currently spendable. This is the balance you can use to initiate new payments. | | `reservedBalance` | Funds currently held aside for in-flight payments. You cannot use this balance to initiate new payments until the reservation is released or consumed. | | `timestamp` | The time at which the balance snapshot was taken. | Balance and payment creation If a payment creation request fails with error `USR_067` (Insufficient balance), compare `availableBalance` against the payment amount. The reserved balance is not available for new payments. ## Step 2: Get ledger transactions Use the **Get ledger transactions** operation to retrieve a paginated list of ledger entries within a date-time range. Each entry shows the operation performed, its effect on your available balance, and the source that created it. ### Endpoint `GET /v2/ledger-transactions` ### Required query parameters | Parameter | Description | Example | | --- | --- | --- | | `currency` | ISO 4217 currency code. | `USD` | | `start-dttm` | Start of the date-time range (inclusive, UTC). | `2025-03-15T00:00:00Z` | | `end-dttm` | End of the date-time range (exclusive, UTC). | `2025-03-16T00:00:00Z` | | `page-size` | Number of records per page. Minimum: 1, maximum: 50. | `25` | ### Example request ```bash curl -X GET "https://api.test.ripple.com/v2/ledger-transactions?\ currency=USD\ &start-dttm=2025-03-15T00:00:00Z\ &end-dttm=2025-03-16T00:00:00Z\ &page-size=25" \ -H "Authorization: Bearer " \ -H "Accept: application/json" ``` ### Example response ```json { "offset": "0", "pageSize": "25", "pageElements": "10", "total": "10", "statementTransactions": [ { "tenant": "acme-corp", "amount": "14.00", "currency": "USD", "operation": "DEBIT", "txnSource": "PAYMENTS", "status": "SUCCESS", "createdDttm": "2025-03-15T10:25:12.000000Z", "updatedDttm": "2025-03-15T10:25:12.000000Z", "availableBalanceBefore": "50014.00", "availableBalanceAfter": "50014.00" }, { "tenant": "acme-corp", "amount": "10000.00", "currency": "USD", "operation": "DEBIT", "txnSource": "PAYMENTS", "status": "SUCCESS", "createdDttm": "2025-03-15T10:25:10.000000Z", "updatedDttm": "2025-03-15T10:25:10.000000Z", "availableBalanceBefore": "50014.00", "availableBalanceAfter": "50014.00" }, { "tenant": "acme-corp", "amount": "10014.00", "currency": "USD", "operation": "RESERVE", "txnSource": "PAYMENTS", "status": "SUCCESS", "createdDttm": "2025-03-15T10:23:45.000000Z", "updatedDttm": "2025-03-15T10:23:45.000000Z", "availableBalanceBefore": "60014.00", "availableBalanceAfter": "50000.00" } ] } ``` ### Understanding ledger operations The `operation` field tells you what action was applied to your account. The sequence of RESERVE → DEBIT is the typical pattern for a completed payment. | Operation | Effect on `availableBalance` | When it occurs | | --- | --- | --- | | `CREDIT` | Increases | Funds are added to your account (for example, a top-up). | | `RESERVE` | Decreases | Funds are set aside when a payment enters the validation or transferring state. | | `DEBIT` | No change (typically) | Reserved funds are consumed when a payment completes. The available balance already decreased at RESERVE time. | | `RELEASE` | Increases | Reserved funds are returned when a payment fails or is cancelled. | | `VOID_BALANCE` | Implementation-specific | Administrative correction. Contact Ripple technical support for details. | | `OVERRIDE_BALANCE` | Implementation-specific | Administrative correction. Contact Ripple technical support for details. | Why DEBIT doesn't change the available balance When a payment starts, the `RESERVE` operation moves funds out of available balance and into a reserved state. When the payment completes, `DEBIT` finalizes the outflow from the reserved amount. But since available balance already decreased at `RESERVE` time, `availableBalanceBefore` and `availableBalanceAfter` are typically equal for a `DEBIT` entry. If a payment fails, a `RELEASE` entry returns the reserved funds to available balance. ## Step 3: Paginate through results If the `total` value in the response is greater than `pageElements`, there are more records to retrieve. Use the `offset` parameter to fetch subsequent pages. **Pattern:** Set `offset` to a multiple of `page-size` to advance through pages. ### Example: Fetch the second page ```bash curl -X GET "https://api.test.ripple.com/v2/ledger-transactions?\ currency=USD\ &start-dttm=2025-03-15T00:00:00Z\ &end-dttm=2025-03-16T00:00:00Z\ &page-size=25\ &offset=25" \ -H "Authorization: Bearer " ``` Continue incrementing `offset` by `page-size` until `pageElements` in the response is less than `page-size`, which indicates you have reached the last page. Fix your time range before paginating Do not change `start-dttm` or `end-dttm` between pages of the same query. Changing the time range mid-pagination can cause you to miss or duplicate records. ## Step 4: Filter by payment ID To find all ledger entries associated with a specific payment, use the `txnReference` parameter. For payments, the `txnReference` value is the `paymentId` returned when the payment was created. This is useful for auditing a specific payment's balance impact (the RESERVE, DEBIT, and any RELEASE entries for that payment). ### Example: Look up ledger entries for a specific payment ```bash curl -X GET "https://api.test.ripple.com/v2/ledger-transactions?\ currency=USD\ &start-dttm=2025-03-15T00:00:00Z\ &end-dttm=2025-03-16T00:00:00Z\ &page-size=25\ &txnReference=aa74f2f4-5996-4f0c-9d8a-7a5e1d51c502" \ -H "Authorization: Bearer " ``` ### Example response ```json { "offset": "0", "pageSize": "25", "pageElements": "2", "total": "2", "statementTransactions": [ { "tenant": "acme-corp", "amount": "10014.00", "currency": "USD", "operation": "DEBIT", "txnSource": "PAYMENTS", "status": "SUCCESS", "createdDttm": "2025-03-15T10:25:10.000000Z", "updatedDttm": "2025-03-15T10:25:10.000000Z", "availableBalanceBefore": "50014.00", "availableBalanceAfter": "50014.00" }, { "tenant": "acme-corp", "amount": "10014.00", "currency": "USD", "operation": "RESERVE", "txnSource": "PAYMENTS", "status": "SUCCESS", "createdDttm": "2025-03-15T10:23:45.000000Z", "updatedDttm": "2025-03-15T10:23:45.000000Z", "availableBalanceBefore": "60014.00", "availableBalanceAfter": "50000.00" } ] } ``` This shows the complete ledger impact of the payment: funds were reserved when the payment was created, and debited when it completed. ## Step 5: Export as CSV For reconciliation workflows, you can request the response as a CSV file by setting the `Accept: text/csv` header. If this header is omitted, the API returns JSON by default. ### Example: Download a CSV statement ```bash curl -X GET "https://api.test.ripple.com/v2/ledger-transactions?\ currency=USD\ &start-dttm=2025-03-01T00:00:00Z\ &end-dttm=2025-04-01T00:00:00Z\ &page-size=50" \ -H "Authorization: Bearer " \ -H "Accept: text/csv" \ -o ledger-march-2025.csv ``` ### CSV format The CSV response includes the same fields as the JSON response, as column headers: ```csv tenant,amount,currency,operation,txnSource,status,createdDttm,updatedDttm,availableBalanceBefore,availableBalanceAfter acme-corp,10014.00,USD,DEBIT,PAYMENTS,SUCCESS,2025-03-15T10:25:10Z,2025-03-15T10:25:10Z,50014.00,50014.00 acme-corp,10014.00,USD,RESERVE,PAYMENTS,SUCCESS,2025-03-15T10:23:45Z,2025-03-15T10:23:45Z,60014.00,50000.00 ``` Pagination applies to CSV too CSV responses are also paginated. For large date ranges, use the `offset` parameter to retrieve subsequent pages and concatenate the results, omitting the header row from all pages after the first. ## Sorting results Use `sort-key` and `sort-direction` to control the order of results. The default sort order is determined by the API if these parameters are omitted. ```bash curl -X GET "https://api.test.ripple.com/v2/ledger-transactions?\ currency=USD\ &start-dttm=2025-03-15T00:00:00Z\ &end-dttm=2025-03-16T00:00:00Z\ &page-size=25\ &sort-key=CREATED_AT\ &sort-direction=DESC" \ -H "Authorization: Bearer " ``` Supported `sort-key` values: | Value | Sorts by | | --- | --- | | `CREATED_AT` | Transaction creation timestamp | | `STATEMENT_OPERATION` | Operation type (CREDIT, DEBIT, etc.) | | `STATEMENT_SOURCE` | Transaction source (PAYMENTS, BANK, etc.) | | `STATEMENT_STATUS` | Ledger transaction status | | `STATEMENT_TXN_REFERENCE` | Transaction reference | | `STATEMENT_UPDATED_AT` | Last update timestamp | ## Error handling | Error code | Status | Description | Action | | --- | --- | --- | --- | | `USR_251` | 400 | Request parameter missing. | A required parameter (`currency`, `start-dttm`, `end-dttm`, or `page-size`) is missing. Add the missing parameter and retry. | | `SYS_301` | 500 | Internal server error. | Retry with exponential backoff. Contact Ripple technical support if the issue persists. | | `CFG_201` | 500 | Invalid configuration. | Unable to retrieve balances due to a configuration issue. Contact Ripple technical support. | | `AUTH_001` | 401 | Unauthorized. | Your token is invalid or expired. Generate a new access token and retry. | ## Summary and next steps In this tutorial, you: 1. Retrieved your current available and reserved balances using `GET /v2/balances`. 2. Fetched a paginated list of ledger transactions for a date range using `GET /v2/ledger-transactions`. 3. Filtered transactions by payment ID using the `txnReference` parameter. 4. Exported results as CSV for reconciliation. **Next steps:** - To understand how ledger operations map to payment lifecycle events, see [Ledger transactions](/products/payments-direct-2/api-docs/concepts/ledger-transactions). - To create payments that will appear as ledger entries, see [Create a payment](/products/payments-direct-2/api-docs/tutorials/create-a-payment). - For balance-related error codes, see [API error codes](/products/payments-direct-2/api-docs/error-codes/api-errors). - For monitoring payment state changes that drive ledger activity, see [Polling](/products/payments-direct-2/api-docs/best-practices/polling) or [Notification webhooks](/products/payments-direct-2/api-docs/best-practices/notification-webhooks).