Skip to content
/api/v1/account/transactions

Signed-delta ledger of recent token transactions (debits, refunds, refills, grants, manual adjustments).

Signed-delta ledger of recent token transactions (debits, refunds, refills, grants, manual adjustments). EXEMPT. Same auth model as `/balance` — accepts session JWT or `X-API-Key`. `delta < 0` is a debit, `delta > 0` is a credit. NOT to be confused with `/api/v1/billing/history` (Stripe charges + admin grants — different table, different sign convention).

Why use this

Per-call signed-delta audit trail — every token movement on the account, ordered by `created_at DESC` (most recent first). EXEMPT (`cost: 0`) so support workflows can fetch full history without debiting. The canonical answer to 'where did my tokens go?' — each row carries the endpoint that consumed (or refunded) the tokens plus a JSONB `metadata` blob with `request_id` for cross-correlation against server logs. Different from `/api/v1/billing/history` in two ways: this endpoint is a per-call ledger (every API call shows up), the other is a per-billing-event ledger (only Stripe charges + admin grants); this endpoint uses signed deltas (negative for debits), the other uses unsigned amounts in cents with a separate `transaction_type` enum.

Common use case

Customer dashboard 'Recent transactions' card; support troubleshooting ('where did my tokens go on April 26?'); automated reconciliation scripts that need to verify a specific request_id was billed correctly.

Signed-delta audit trail for every token movement on the account — both debits (billed API calls) and credits (refills, grants, refunds, manual adjustments). The canonical 'where did my tokens go?' endpoint. EXEMPT (cost: 0) so support workflows can paginate freely. Each row carries request_id in metadata so a customer dispute can be correlated against server logs deterministically. Different from GET /api/v1/billing/history — that endpoint is the per-Stripe-charge wallet ledger, this is the per-API-call token ledger. For live balance use GET /api/v1/account/balance; for daily aggregation use GET /api/v1/account/usage; for self-serve billing use POST /api/v1/account/billing-portal.

Parameters

NameInRequiredDefaultAllowedDescriptionExample
limitqueryoptional50Number of recent transactions to return (1-200; clamped at the bounds; non-numeric falls back to 50). 50 is the canonical dashboard default; 200 for export workflows; 20 for compact widgets.50

Response schema

FieldTypeNullableDescription
transactionsarraynoArray of signed-delta transaction rows, sorted by `created_at DESC` (most recent first). Empty array on freshly-registered accounts that have neither been granted free-tier tokens (race window before `ensure_ledger_row` fires) nor called any billed endpoint. Cap of 200 rows enforced server-side.
transactions[].created_atstringnoISO-8601 UTC timestamp the transaction was recorded. For debits this is the API call's request-completion time (within milliseconds of the response being sent); for `subscription_refill` events this is the Stripe webhook arrival time.
transactions[].deltaintegernoSigned token movement — NEGATIVE for debits (e.g. `-5` for a 5-token API call), POSITIVE for credits (`+200000` for a paid-plan refill, `+2000` for a free-tier signup grant, `+10` for an admin manual adjustment). Zero for status-only events (e.g. `subscription_cancelled`, `payment_failed`) where token balance does not move but the event must be recorded for audit. Sum across all rows in the current cycle = `current_balance - monthly_quota`.
transactions[].reasonstringnoTransaction kind — one of `debit` (billed API call), `refund` (per-call refund, e.g. handler error), `subscription_refill` (monthly Stripe charge → token grant), `signup_grant` (free-tier 2,000-token initial grant), `manual_adjustment` (admin-applied credit/debit), `subscription_cancelled` / `payment_failed` (status-only, `delta=0`). Use to dispatch UI badges and audit-trail filters.
transactions[].endpointstringyesEndpoint identifier in `METHOD /path` format for `debit` and `refund` rows (e.g. `GET /api/v1/sec/filings`). Null for non-call events (`subscription_refill`, `signup_grant`, `manual_adjustment`, status-only events) — these are account-level movements unattached to a specific endpoint.
transactions[].metadataobjectyesJSONB blob with event-specific context. For `debit`/`refund`: `{request_id, cost_tier}` (correlate with server logs via `request_id`). For `subscription_refill`: `{stripe_invoice_id, plan}`. For `manual_adjustment`: `{admin_user_id, reason}`. For status-only events: `{stripe_event_id, error_code}`. Null when the row was inserted by an early-Phase-56 path that did not yet write metadata.
transactions[].response_statusintegeryesHTTP status code the handler returned for this request. Populated for `debit` rows from 2026-05-18 onward (issue #260). Null on `refund` / `subscription_refill` / `signup_grant` / `manual_adjustment` rows — those are bookkeeping movements, not responses to a specific API call. Null on `debit` rows that pre-date the migration (the column was just added; back-population was not attempted). After the 2026-05-18 batch-1 #254 change, any `debit` row with `response_status >= 400` is always paired with an immediate `refund` row (net-zero on the ledger), so this field is mainly an audit trail rather than a billing-correctness signal.
countintegernoNumber of transaction rows in the response (matches `transactions.length`). Bounded by the `limit` query parameter; smaller when the account has fewer transactions than requested.
as_ofstringnoISO-8601 UTC timestamp the snapshot was generated server-side. NOT cached — always reflects live state.

Sample response

·
  • "transactions":
    ]
  • "count": 3
  • "as_of": "2026-05-02T15:51:00.000Z"
}

Errors

StatusLabelDescription
200OKRequest succeeded.
400Bad RequestInvalid query, body, or path parameter.
401UnauthorizedMissing or invalid Authorization header / api_Token.
402Payment RequiredInsufficient token balance for this call. Top up
429Too Many RequestsRate limit exceeded for your tier (see /pricing for tier limits). Tier limits
500Server ErrorUnexpected server-side failure. Retry with backoff; report if persistent.

Code samples

curl "https://api.finradar.ai/api/v1/account/transactions" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Generate an API key in /account/credentials to run live queries (literal YOUR_API_KEY placeholder shown until then).