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

# Account transactions

> Read posted banking transactions and active pending holds for your organization’s checking accounts using the Payout API.

Retrieve banking activity for **one account belonging to the organization authenticated by your API key**. This includes account movements beyond payouts created through the API. For all of your organization’s eligible accounts, list them first and retrieve transactions separately for each account.

See the [endpoint reference](/api-reference/account/list-account-transactions) and [transaction webhooks](#transaction-webhooks).

`GET /accounts/{accountId}/transactions` uses the existing Payouts API Bearer key. Use an account ID from [`GET /accounts`](/api-reference/account/list-payout-source-accounts). Access is limited to the same open, unlocked operational checking accounts. Missing or invalid keys receive 401, unsupported roles 403, and inaccessible accounts 404.

## Request

```bash theme={null}
curl --get "https://payouts.api.trykarat.com/accounts/4f266e59-5dae-49f7-9ef9-9bdf6d2b7c86/transactions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "status=posted" \
  --data-urlencode "startTime=2026-10-01T00:00:00Z" \
  --data-urlencode "endTime=2026-10-05T00:00:00Z" \
  --data-urlencode "limit=100" \
  --data-urlencode "offset=0"
```

Omit `status` to include both posted and active pending transactions.

## Query

| Parameter | Meaning |
| - | - |
| status | `pending` or `posted`; omitted includes both |
| startTime | Inclusive RFC3339 timestamp, with timezone |
| endTime | Exclusive RFC3339 timestamp, with timezone; defaults to request time |
| limit | Positive integer; default 100, capped at 100 |
| offset | Non-negative integer; default 0 |

Results use the existing Payouts list response: `data` and `meta: { total, limit, offset }`. `total` counts all records matching the account, status and date filters, including on an empty page beyond the end. Increase `offset` by `limit` to request the next page.

Results are ordered ascending by transaction timestamp, then ID. Keep date/status filters fixed while paging, including an explicit `endTime` for a fixed upper bound. Pagination is not a snapshot: pending entries may complete and late postings may arrive between requests, shifting offsets. Deduplicate by ID and repeat reconciliation to converge.

```json theme={null}
{
  "data": [{
    "id": "transaction_example",
    "accountId": "4f266e59-5dae-49f7-9ef9-9bdf6d2b7c86",
    "amount": -12500,
    "currency": "USD",
    "status": "posted",
    "transactionAt": "2026-10-01T10:00:00Z",
    "postedAt": "2026-10-01T10:00:00Z",
    "timestampSource": "provider",
    "description": "Outgoing transfer",
    "type": "account_transfer_intention",
    "relatedTransactionId": null
  }],
  "meta": { "total": 1, "limit": 100, "offset": 0 }
}
```

Amounts are signed integer minor units (USD cents), relative to the selected account. Positive is credit; negative is debit. Pending USD amounts represent holds, not booked movements. `postedAt` is null for pending entries. All provider categories are included; accept unfamiliar `type` values. `relatedTransactionId` is the provider-supplied associated transaction, when present; it is not a guaranteed pending-to-posted match. Do not match records by amount or description. A posted record and its preceding pending record have separate IDs. Returns are separate credits/debits.

## Synchronization

1. Backfill posted transactions for the needed time range, incrementing `offset` by `limit` through every page; upsert by `id`.
2. Poll posted transactions using overlapping date windows and deduplicate by `id`. Local ingestion is asynchronous; a posting timestamp is not an ingestion watermark. Periodically reconcile older windows too.
3. Refresh the complete pending set using `status=pending` without a lower date bound. Replace the locally held set only after fetching all pages successfully. Repeat to converge when entries change during pagination.
4. Compare posted movements with posted balances over matching boundaries. The existing `availableBalance` includes holds and is not a posted-balance reconciliation target.

Invalid query parameters receive 400. Retrieval failures receive an error, never a successful partial page. No transaction webhook is required to use this endpoint.

Legacy records without a provider timestamp use their database creation time for `transactionAt`, date filtering and ordering, with `timestampSource: "recorded"` and `postedAt: null`. This preserves older account movements without claiming to know their exact booking time. Records with provider timestamps use `timestampSource: "provider"`.

## Transaction webhooks

Subscribe to `transaction.pending`, `transaction.updated`, `transaction.posted`, and `transaction.pending_completed` for changes after subscription creation. See [Webhooks](/developers/webhooks#transaction-events) for payloads, signature verification, revision ordering, and recovery. Continue periodic endpoint reconciliation even when using webhooks.
