Send
X-Hevn-Account: cl_… with your own access token to act for one client. On a resource route
like GET /banks the header is optional: omit it and the call acts on your integrator account
instead. The singular /client* routes require it — the header is the only thing that names the
account — and /clients and /escrow* refuse it.
X-Hevn-Account is required rather than optional. Omit it and the call answers 422 validation_failed for a missing header — reading your own account means sending your own cl_….
Balance
Response — 200
balance carries the token’s own precision, usdValue and totalUsd are rounded to cents. baseSmartWallet is the address funds live at and the address a crypto payer sends to; it is the only address on this surface.
The read hits the chain, so it is the truth about spendable funds — and it is what POST /dapi/v1/payouts checks before it lets you sign. A payout refused with insufficient_funds and a balance that looks sufficient means the difference is an in-flight debit, not a stale cache.
Walk the ledger
GET /dapi/v1/transactions is cursor-paged, newest first. Pass nextCursor back as cursor until it is gone. There is no offset and no total.
Response — 200
from is what left the source side and to what arrived at the destination; on a same-asset movement they are equal. isIncome is the direction, counterparty is the resolved name of the other party, and txHash is the on-chain leg where there is one. A cursor belongs to the query that produced it: change a filter and start again, or the call answers 400 invalid_cursor.
Filters
Every filter is a query parameter, camelCase, and the list-shaped ones take comma-separated values.
Values are matched exactly, case included. A value outside the set answers
400 invalid_request with the offending one in details.reason, rather than returning a silently narrower page.
Totals for the same filters
GET /dapi/v1/transactions/summary takes the same filters and answers the aggregate, in USD, settled and pending kept apart:
Response — 200
One transaction
GET /dapi/v1/transactions/{transactionId} returns the same row plus description, explorerUrl, traceNumber and attachmentIds (doc_…). Use it when you have an id — from a payout’s transactionId, from a sandbox credit, or from a row you are reconciling.
Exports
GET /dapi/v1/transactions/export streams a file. The name arrives in Content-Disposition; there is no JSON body and no document to fetch afterwards.
download is the one method that writes bytes instead of parsing JSON —
the reference client has it.
Every ledger filter applies to an export as well, so a statement can be narrowed the same way a page can. A statement with no from/to covers the current month to now. Asking for a combination the table does not list — a receipt as xlsx, a statement without bankId — answers 422 validation_failed naming the parameter at fault.
Reconciling
The ledger is the durable record of everything the other pages produce: a confirmed payout, a transfer, a settled payin, a sandbox credit. Reconcile with a watermark rather than a re-read:- Keep the newest
createdAtyou have processed, per client. - Ask for
from=<watermark>and walk the cursor to the end. - Match your own records on
id, and a payout on thetransactionIdits read returns —txHashidentifies the on-chain leg, not the payment. - Move the watermark only after the whole walk succeeded. Ids are stable, so replaying an overlap costs a comparison, and skipping a row costs a missing payment.
pending row is not an error; a row that never appears is, and its payin or payout id is where to look.
Next: Escrow
Lock one client’s funds in an on-chain contract while another delivers: the marketplace order, end to end.