> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.thepennyinc.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.thepennyinc.com/_mcp/server.

# List ledger entries

GET https://sandbox.api.thepennyinc.com/ledger/

List all ledger entries for the business.

Required permissions: `ledger:list`.

Reference: https://docs.thepennyinc.com/banking/api-reference/treasury/ledger/list

## Authentication

- `Authorization` header (bearer token, required) — Bearer authentication of the form `Bearer <token>`, where token is your auth token.

## Servers

- `https://sandbox.api.thepennyinc.com` (Sandbox — safe for testing, no real money movement., default)
- `https://live.api.thepennyinc.com` (Live — real businesses, real money movement.)

## Request

### Query parameters

- `page_size` (integer, optional, default: 100) — Maximum number of results to return per page. Defaults to 100.
- `next_page_token` (string, optional, nullable) — Pagination key used to retrieve the next page of results.
- `applied_time_greater_than_equal_to` (string, optional, nullable) — Lower time bound for Applied Time, inclusive.
- `applied_time_greater_than` (string, optional, nullable) — Lower time bound for Applied Time, exclusive.
- `applied_time_equal_to` (string, optional, nullable) — Exact timestamp for Applied Time.
- `applied_time_less_than_equal_to` (string, optional, nullable) — Upper time bound for Applied Time, inclusive.
- `applied_time_less_than` (string, optional, nullable) — Upper time bound for Applied Time, exclusive.

### Headers

- `X-Penny-As-Business` (string, optional, nullable) — Act on behalf of another business that has granted you access. Requires the `business:act_as` permission.

## Response

### 200

A list of ledger entries.

- `items` (list of LedgerEntry, required) — The list of items returned by the API.
- `count` (integer, required) — The total number of items returned in this response.
- `next_page_token` (string, optional, nullable) — A token for retrieving the next page of results, if applicable.

## Errors

### 400 Bad Request Error

The request was malformed: a required field is missing or a value has the wrong type or format.

- `type` (string, required) — The name of the exception that was raised.
- `message` (string, required) — A human-readable description of the error.
- `details` (map from string to any, optional, nullable) — Structured context about the error, if any.
- `trace_id` (string, optional, nullable) — Identifier for correlating this error with server-side logs.
- `errors` (list of map from string to any, optional, nullable) — Sub-errors that contributed to this failure, if any.

### 401 Unauthorized Error

Authentication failed.

- `type` (string, required) — The name of the exception that was raised.
- `message` (string, required) — A human-readable description of the error.
- `details` (map from string to any, optional, nullable) — Structured context about the error, if any.
- `trace_id` (string, optional, nullable) — Identifier for correlating this error with server-side logs.
- `errors` (list of map from string to any, optional, nullable) — Sub-errors that contributed to this failure, if any.

### 403 Forbidden Error

The caller does not have permission to perform this action.

- `type` (string, required) — The name of the exception that was raised.
- `message` (string, required) — A human-readable description of the error.
- `details` (map from string to any, optional, nullable) — Structured context about the error, if any.
- `trace_id` (string, optional, nullable) — Identifier for correlating this error with server-side logs.
- `errors` (list of map from string to any, optional, nullable) — Sub-errors that contributed to this failure, if any.

### 422 Unprocessable Entity Error

The request was well-formed but could not be processed because it breaks a business rule.

- `type` (string, required) — The name of the exception that was raised.
- `message` (string, required) — A human-readable description of the error.
- `details` (map from string to any, optional, nullable) — Structured context about the error, if any.
- `trace_id` (string, optional, nullable) — Identifier for correlating this error with server-side logs.
- `errors` (list of map from string to any, optional, nullable) — Sub-errors that contributed to this failure, if any.

### 429 Too Many Requests Error

Too many requests; retry after the Retry-After header.

- `type` (string, required) — The name of the exception that was raised.
- `message` (string, required) — A human-readable description of the error.
- `details` (map from string to any, optional, nullable) — Structured context about the error, if any.
- `trace_id` (string, optional, nullable) — Identifier for correlating this error with server-side logs.
- `errors` (list of map from string to any, optional, nullable) — Sub-errors that contributed to this failure, if any.

### 500 Internal Server Error

An unexpected error occurred.

- `type` (string, required) — The name of the exception that was raised.
- `message` (string, required) — A human-readable description of the error.
- `details` (map from string to any, optional, nullable) — Structured context about the error, if any.
- `trace_id` (string, optional, nullable) — Identifier for correlating this error with server-side logs.
- `errors` (list of map from string to any, optional, nullable) — Sub-errors that contributed to this failure, if any.

## Types

### LedgerEntry

A record of a change to an account's balance. Use ledger entries to reconcile your records and review balance history.

- `ledger_entry_id` (string, required) — Unique identifier for this ledger entry.
- `direction` (enum, required) — Direction of the ledger entry. A debit represents value deducted from the account, while a credit represents value added to the account.
  - Allowed values: `debit`, `credit`
- `currency` (enum, required) — ISO 4217 currency code for the monetary values represented by this ledger entry.
  - Allowed values: `USD`
- `available_balance_change` (string, required) — Amount applied to the account's available balance by this ledger entry. The available balance represents funds currently available for use.
- `total_balance_change` (string, required) — Amount applied to the account's total balance by this ledger entry. The total balance includes all funds recorded against the account, including amounts that may not yet be available for use.
- `applied_time` (datetime, required) — Date and time at which the ledger entry was applied to the account's balances, represented as an ISO 8601 timestamp.
- `business_id` (string, required) — Unique identifier of the business associated with this ledger entry.
- `business_entity_id` (string, required) — Unique identifier of the business entity associated with this ledger entry.
- `program_id` (string, required) — Unique identifier of the program under which this ledger entry was recorded.
- `type` (enum, required) — Type of financial activity that resulted in this ledger entry.
  - Allowed values: `payment`, `transfer`
- `channel` (enum, required) — Channel through which the financial activity associated with this ledger entry was processed.
  - Allowed values: `internal`, `card`, `bank`, `system`
- `source` (LedgerSourceResponse, required) — References to the originating transaction and transaction event associated with this ledger entry.
- `account_id` (string, optional, nullable) — Unique identifier of the account affected by this ledger entry.
- `control_account_id` (string, optional, nullable) — Unique identifier of the associated Control account, when applicable. This field is omitted when the ledger entry is not associated with a Control account.

### LedgerSourceResponse

Identifiers linking a ledger entry to the transaction and transaction event that produced it.

- `transaction_id` (string, required) — The transaction this ledger entry was recorded for.
- `transaction_stage` (integer, required) — The stage of the transaction's lifecycle at which this entry was recorded.
- `transaction_event_id` (string, required) — The specific transaction event that produced this ledger entry.

## Examples

**Response**

```json
{
  "items": [
    {
      "ledger_entry_id": "ledger_entry_01937394-e0a9-7dfe-8071-e0a9dfe07161",
      "direction": "debit",
      "currency": "USD",
      "available_balance_change": "100.00",
      "total_balance_change": "100.00",
      "applied_time": "2024-01-15T10:30:00Z",
      "business_id": "business_01937b95-484e-75af-8c68-484e5afc68d3",
      "business_entity_id": "business_entity_01937c9d-3a1e-72b0-8881-3a1e2b088159",
      "program_id": "program_019377de-7f88-7f02-894f-7f88f0294fcb",
      "type": "payment",
      "channel": "internal",
      "source": {
        "transaction_id": "transaction_01937a7d-ad6b-77ca-8046-ad6b7ca046ce",
        "transaction_stage": 1,
        "transaction_event_id": "transaction_event_01937dd5-0f62-7e20-810f-0f62e2010f7d"
      },
      "account_id": "account_019372e3-b8dc-7de2-80b6-b8dcde20b6c9",
      "control_account_id": "account_019372e3-b8dc-7de2-80b6-b8dcde20b6c9"
    }
  ],
  "count": 1,
  "next_page_token": "string"
}
```

**SDK Code**

```python
import requests

url = "https://sandbox.api.thepennyinc.com/ledger/"

headers = {
    "X-Penny-As-Business": "business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71",
    "Authorization": "Bearer <token>"
}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://sandbox.api.thepennyinc.com/ledger/';
const options = {
  method: 'GET',
  headers: {
    'X-Penny-As-Business': 'business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71',
    Authorization: 'Bearer <token>'
  }
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://sandbox.api.thepennyinc.com/ledger/"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("X-Penny-As-Business", "business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71")
	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://sandbox.api.thepennyinc.com/ledger/")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["X-Penny-As-Business"] = 'business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71'
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://sandbox.api.thepennyinc.com/ledger/")
  .header("X-Penny-As-Business", "business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://sandbox.api.thepennyinc.com/ledger/', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'X-Penny-As-Business' => 'business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://sandbox.api.thepennyinc.com/ledger/");
var request = new RestRequest(Method.GET);
request.AddHeader("X-Penny-As-Business", "business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71");
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "X-Penny-As-Business": "business_01a083e2-82ed-7a5c-9d1e-3b6f0c2a4d71",
  "Authorization": "Bearer <token>"
]

let request = NSMutableURLRequest(url: NSURL(string: "https://sandbox.api.thepennyinc.com/ledger/")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```