---
title: "List balance changes for a period"
method: GET
path: "/internal-accounts/{id}/balance-changes"
tags: ["Periodic Statements"]
---

# List balance changes for a period

`GET /internal-accounts/{id}/balance-changes`

## Request

- Base URL: `https://api.lightspark.com/grid/2025-10-13`
- URL: `https://api.lightspark.com/grid/2025-10-13/internal-accounts/{id}/balance-changes`
- Auth: HTTP basic

Every change to this account's balance in a window, in the order the money moved, with the opening and closing balances for that window in the same response.

`GET /transactions` returns one row per transaction. This returns one row per change to the balance, and a transaction that moves the balance more than once produces more than one change: an ACH deposit and its later return are two, and a card purchase that clears in two parts is two. Each change's `transactionId` names its transaction, so fetch it from `GET /transactions/{transactionId}` for its type, counterparty, merchant and rail.

**The identity to assert:** `openingBalance + Σ(data[].amount) == closingBalance`, summed over every page. The opening and closing balances describe the window rather than the page, so they are the same on every page. Page until `hasMore` is false, then assert the identity.

`startDate` and `endDate` are instants in any timezone, UTC included, and the window is half-open: a change at exactly `endDate` belongs to the next window. Consecutive windows therefore tile with no gap and no overlap.

A window whose card settlement has not closed is refused with `409 NOT_YET_AVAILABLE`, because its figures could still change. Retry once it has settled.

A fee is already inside a change's `amount`. For the fee itself, read `fees` on the change's transaction, counting each transaction once.

## Query parameters

- `startDate` string, date-time, required
- `endDate` string, date-time, required
- `limit` integer
- `cursor` string

## Response `200`

The balance changes in the window, with the balances that bound it

- BalanceChangeListResponse: A window of balance changes with the balances that bound it. The opening and closing balances describe the whole window, not the page, so they are the same on every page, and the identity `openingBalance + Σ(data[].amount) == closingBalance` holds only once every page's `data` is summed.
  - `data` BalanceChange[], required: Balance changes on this page, ordered by `effectiveAt`
    - `id` string, required: Stable identifier for this balance change
    - `transactionId` string: The transaction this change belongs to. Fetch it with `GET /transactions/{transactionId}` for its type, counterparty, merchant and rail. Several changes can share one transaction, for example an ACH deposit and its return, or a card purchase that settles in parts. Absent for an adjustment with no transaction behind it.
    - `amount` CurrencyAmount, required
      - `amount` integer, required: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
      - `currency` Currency, required
        - `code` string: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
        - `name` string: Full name of the currency
        - `symbol` string: Symbol of the currency
        - `decimals` integer: Number of decimal places for the currency
    - `effectiveAt` string, date-time, required: When the account holder's balance moved. Changes are ordered by this time.
  - `startDate` string, date-time, required: Start of the window, inclusive
  - `endDate` string, date-time, required: End of the window, exclusive
  - `openingBalance` CurrencyAmount, required
    - `amount` integer, required: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
    - `currency` Currency, required
      - `code` string: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
      - `name` string: Full name of the currency
      - `symbol` string: Symbol of the currency
      - `decimals` integer: Number of decimal places for the currency
  - `closingBalance` CurrencyAmount, required
    - `amount` integer, required: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
    - `currency` Currency, required
      - `code` string: Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
      - `name` string: Full name of the currency
      - `symbol` string: Symbol of the currency
      - `decimals` integer: Number of decimal places for the currency
  - `hasMore` boolean, required: Indicates if more changes are available beyond this page
  - `nextCursor` string: Cursor to retrieve the next page of results (only present if hasMore is true)
  - `totalCount` integer: Number of balance changes in the window, across all pages

## Other responses

- `400`: Bad request. Returned when `startDate` or `endDate` is missing, has no timezone, or is in the future, when `startDate` is not before `endDate`, when `cursor` was not issued by this endpoint for the same account and window, or when the account has no statement of its own.
- `401`: Unauthorized
- `404`: Internal account not found
- `409`: The window is not final yet. Card settlement for one of its boundaries has not closed, so its balances and changes could still change. Retry once it has settled.
- `500`: Internal service error

## Changes

> 115 revisions in range; 2 not diffed.

- **2026-10-28** `d996ddfb9d2b`: 2 info
  - added the optional property `details/missingFields` to the response with the `400` status
  - added the optional property `details/refusalReason` to the response with the `400` status
- **2026-10-26** `f11f1e76bdd7`: 1 warning
  - added the new `PURCHASE_CARD_LIMIT_REACHED` enum value to the `code` response property for the response status `409`
- **2026-10-26** `0a6dad5815c7`: 1 warning
  - added the new `INVOICE_ALREADY_USED` enum value to the `code` response property for the response status `409`
- **2026-10-24** `715332dcb111`: 1 warning
  - added the new `EXACT_AMOUNT_UNAVAILABLE` enum value to the `code` response property for the response status `400`
- **2026-10-20** `761d1d030cb5`: 2 warning
  - added the new `AGENT_CARD_EXISTS` enum value to the `code` response property for the response status `409`
  - added the new `CARDHOLDER_AGREEMENT_NOT_ACCEPTED` enum value to the `code` response property for the response status `400`

[Operation history](https://skmtc.dev/lightsparkdev/apis/grid-api/changes/internal-accounts/:id/balance-changes/get.md)

---

[API](https://skmtc.dev/lightsparkdev/apis/grid-api.md) - [All operations](https://skmtc.dev/lightsparkdev/apis/grid-api/llms.txt) - [OpenAPI document](https://skmtc.dev/lightsparkdev/apis/grid-api/revisions/7a1db46ec552?raw)
