Reconcile transactions
Page through every on-chain movement in and out of your wallets, and look up a single transaction.
GET /api/v1/transactions lists on-chain movements in and out of your wallets, newest first. Page
through it with a cursor to reconcile your ledger against ours.
Payouts are followed in /withdrawals.
The transactions list holds on-chain movements only. A payout that is not on the network yet — for
example one waiting for approval — is not in it. Follow payouts with
GET /api/v1/withdrawals.
Query parameters
| Parameter | Type | Notes |
|---|---|---|
limit | integer | 1–100. Default 25. |
cursor | string | Opaque. Pass meta.next_cursor from the previous page. A malformed cursor returns 400 validation_failed. |
created_after | ISO 8601 | Optional range filter: only movements recorded after this time. |
created_before | ISO 8601 | Optional range filter: only movements recorded before this time. |
wallet_id | string | Optional. Restrict to one wallet. |
A call without cursor, created_after or created_before returns the newest page.
The range filters apply to the time we recorded the movement, which can be well after its block time. A movement mined just before a boundary can therefore land in the next range. Reconcile consecutive ranges back to back and every movement falls in exactly one of them.
Response
| Field | Type | Notes |
|---|---|---|
id | string | Transaction id. A move between two of your own wallets is two rows with the same id. |
direction | string | in · out · internal. |
status | string | Normalised stage, e.g. completed, broadcasting. |
tx_hash | string|null | Null until the transfer reaches the network. |
from / to | object | { name, address }. name is null for an outside party. |
amount, asset | string | Decimal string and asset symbol. |
fee, fee_asset | string|null | The network fee, folded into its payout row. |
network, network_name, wallet_id | string|null | Where the movement happened. |
meta.next_cursor | string|null | Cursor for the next (older) page; null on the last page. |
{
"data": [
{
"id": "9c21d0e4-3b7a-4f58-a1c6-2e8f7b90d4a3",
"created_at": "2026-09-15T08:31:21.823Z",
"direction": "out",
"from": { "name": "Operating Wallet", "address": "0xe8d8…a119" },
"to": { "name": null, "address": "0x03a6…81b9" },
"amount": "0.01",
"asset": "ETH",
"fee": "0.0000467",
"fee_asset": "ETH",
"status": "completed",
"tx_hash": "0xfd31…e730",
"network": "ethereum",
"network_name": "Ethereum",
"wallet_id": "acct_7f3a…"
}
],
"meta": { "count": 1, "limit": 25, "next_cursor": null }
}A read that can't be completed fails with an error — for example 503 service_unavailable — never
with a partial page. Retry it with a newly signed request.
Page with the cursor
Follow meta.next_cursor until it is null. That is the only reliable end-of-list signal:
- A page may hold slightly fewer rows than
limit, because network fees fold into their payout row. - A page may hold more rows than
limit, because a move between two of your own wallets is two rows (anoutand anin).
So never stop because a page came back short, and never page by moving created_before yourself —
created_after and created_before are range filters, not a paging mechanism. To reconcile a period,
set the range once and keep it on every request while you follow the cursor.
// Every movement recorded in September 2026, newest first.
const range = { created_after: "2026-09-01T00:00:00Z", created_before: "2026-10-01T00:00:00Z" };
let cursor = null;
do {
const query = new URLSearchParams({ ...range, limit: "100", ...(cursor ? { cursor } : {}) });
const { status, body } = await api.request("GET", `/api/v1/transactions?${query}`);
if (status !== 200) throw new Error(JSON.stringify(body));
for (const row of body.data) upsert(`${row.id}:${row.direction}`, row); // idempotent write
cursor = body.meta.next_cursor;
} while (cursor);Store rows keyed by id and direction: the two legs of an internal move share an id. Writing
idempotently means a re-run of the same range is harmless.
Get one transaction
GET /api/v1/transactions/{id} returns data as an array of legs:
- one leg for a deposit or a payout;
- two legs — an
outand anin— for a move between two of your own wallets.
Each leg has the same fields as a list row. An id outside your workspace returns
404 transaction_not_found.
{
"data": [
{
"id": "9c21d0e4-3b7a-4f58-a1c6-2e8f7b90d4a3",
"created_at": "2026-09-15T08:31:21.823Z",
"direction": "out",
"from": { "name": "Operating Wallet", "address": "0xe8d8…a119" },
"to": { "name": null, "address": "0x03a6…81b9" },
"amount": "0.01",
"asset": "ETH",
"fee": "0.0000467",
"fee_asset": "ETH",
"status": "completed",
"tx_hash": "0xfd31…e730",
"network": "ethereum",
"network_name": "Ethereum",
"wallet_id": "acct_7f3a…"
}
],
"meta": { "count": 1 }
}