Reading Transactions & Ledger Entries

Filter, page through, and follow up on transaction activity.

See Transactions first for what type, direction, and status mean. All requests go to Penny Banking.

List a card’s recent transactions

curl "https://sandbox.api.thepennyinc.com/transactions/?card_id=card_019375de-a2a0-7f31-884a-a2a0f3184abd&page_size=50" \
-H "Authorization: Bearer $ACCESS_TOKEN"

GET /transactions/ accepts at most one scope filter per request: account_id, card_id, cardholder_id, control_account_id, or program_id. Sending more than one returns 422. Omit the scope filter to list transactions across your whole business. Results are paginated with next_page_token:

page = requests.get(f"{BANKING}/transactions/", headers=headers, params={"page_size": 50}).json()
while page.get("next_page_token"):
page = requests.get(
f"{BANKING}/transactions/",
headers=headers,
params={"page_size": 50, "next_page_token": page["next_page_token"]},
).json()

Filter by date range

Transaction timestamps are filtered on stage_time: when the transaction last advanced through its lifecycle, not necessarily when it was created. You can add one scope filter such as card_id or account_id to a stage_time range, except control_account_id, which can’t be combined with stage_time filters:

curl "https://sandbox.api.thepennyinc.com/transactions/?stage_time_greater_than_equal_to=2026-08-01T00:00:00Z&stage_time_less_than=2026-09-01T00:00:00Z" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Look up one transaction in detail

curl "https://sandbox.api.thepennyinc.com/transactions/$TRANSACTION_ID" \
-H "Authorization: Bearer $ACCESS_TOKEN"
curl "https://sandbox.api.thepennyinc.com/transactions/$TRANSACTION_ID/events" \
-H "Authorization: Bearer $ACCESS_TOKEN"
curl "https://sandbox.api.thepennyinc.com/transactions/$TRANSACTION_ID/history" \
-H "Authorization: Bearer $ACCESS_TOKEN"

GET /transactions/{transaction_id} returns the latest state by default. Pass stage and version to read an earlier snapshot; 0 (the default for both) selects the latest.

Use stage (on the transaction itself) to tell whether a given event is still the latest one. See Transactions.

Find transactions by your own reference

If you set client_reference when you started a movement (for example, on POST /accounts/capital/transfer), look up the resulting transactions with it. References don’t need to be unique, so the response is a paginated list:

curl "https://sandbox.api.thepennyinc.com/transactions/by-client-reference?client_reference=budget-2026-09-marketing" \
-H "Authorization: Bearer $ACCESS_TOKEN"

A transfer carries its client_reference onto both of its transactions, so this returns the outbound and inbound sides together.

Reading the ledger directly

Where a transaction is the record of an activity, a ledger entry is the resulting posting against a specific account’s balance:

curl "https://sandbox.api.thepennyinc.com/accounts/capital/$ACCOUNT_ID/ledger" \
-H "Authorization: Bearer $ACCESS_TOKEN"

Prefer webhooks over polling for anything you need to react to in near-real-time — see Subscribing to Webhooks.