Accounts, wallet and transactions endpoints
GET /accounts (auth)
The user's chain accounts and which are still to be provisioned.
POST /accounts (auth)
Link an address: { chain, address, walletProvider, accountType }. Refused if the address belongs to another user.
GET /balances (auth)
USDC balance on each chain where the user has an account: { balances: [{ chain, symbol, amount }] }. amount is null if that chain could not be read.
POST /transfers/prepare (auth)
Send USDC on one chain: { chain, symbol: "USDC", to, amount }.
GET /deposit-addresses (auth)
The user's personal deposit addresses. USDC sent to one is moved to the user's hub wallet automatically; nothing to sign.
{
"hub": { "chain": "stellar-testnet", "name": "Stellar Testnet", "address": "C..." },
"deposits": [
{ "chain": "base-sepolia", "name": "Base Sepolia", "address": "0x...", "assets": ["USDC"], "minimum": "1" }
]
}
Deposits appear as transfers in GET /routing once BlockFinaX flushes them.
POST /routing/quote (auth)
Quote moving USDC between a funding network and the hub.
{ "kind": "fund", "network": "base-sepolia", "amount": "100" }
kind is fund (network to hub, into the user's hub account) or withdraw (hub to network; optional recipient, defaulting to the user's own account there). Returns { quotes: RoutingQuote[] }, each with provider, amountIn, amountOut (after the most Circle may charge), totalFees, estimatedSeconds, expiresAt.
POST /routing/execute (auth)
Same body. Starts the best route and returns { route, transactions }: the source-network steps to sign. A step with continues: true must confirm before the next can be prepared.
POST /routing/:id/continue (auth)
Returns the next source step: { route, transactions }.
POST /routing/:id/source (auth)
Body: { "txHash": "..." }, the hash of the final source step. BlockFinaX then follows Circle's attestation and delivers on the destination.
GET /routing (auth), GET /routing/:id (auth)
The user's transfers: id, kind, sourceChain, destinationChain, recipient, amount, amountOut, maxFee, state (REQUESTED, SOURCE_CONFIRMED, ROUTING, DESTINATION_CONFIRMED, ACTION_COMPLETED, RECOVERY_REQUIRED, REFUNDED), sourceTxHash, destinationTxHash, error.
POST /transactions/relay (auth)
Body: { chain: "stellar-testnet", xdr }. Checks the call is on the sponsorship allowlist and authorised by the user's wallet, submits it through OpenZeppelin Channels with a BlockFinaX fee account as the fallback, and returns { chain, state, hash } with state CONFIRMED or SUBMITTED.
When the request carries X-BFX-Organisation, the call is checked against the member's role: admins may send pool calls, transfers and changes to the business account; operators pool calls only; viewers nothing.
Acting for a business account
Send X-BFX-Organisation: <id> with any request under /api/v2 to act for a business account the signed-in user belongs to. Balances, positions, quotes and prepared transactions then use the business account. The API checks active membership on every request and answers 401 otherwise. Request a quote, GET /deposit-addresses and /routing refuse the header: they work from personal accounts only, for now.
Business account endpoints
These live under /api/organisations and need a signed-in user.
| Method and path | Who | Does |
|---|---|---|
GET /config | Anyone | Whether business accounts are offered, the contract addresses, and whether operators are available |
GET / | Signed in | The user's business accounts and role in each |
POST / { name } | Signed in, with a passkey | Create one and deploy its account (at most three per person) |
GET /:id | Member | Members, roles, rule ids, the account address |
GET /:id/history | Member | Changes, with transaction hashes |
POST /:id/invites { email, role } | Admin | Invite; emails a one-time link and returns it |
POST /invites/accept { token } | The invited email | Accept |
POST /:id/members/:memberId/revoke | Admin | Withdraw an invitation that is not yet on the account |
POST /:id/members/:memberId/changes { kind, role? } | Admin | Start activate, remove or role; returns the first step |
POST /:id/members/:memberId/next | Admin | Prepare the current step again |
POST /:id/members/:memberId/confirm { hash } | Admin | Confirm the current step from chain state; returns the next step or the result |
A step is { memberId, step, stepsLeft, xdr, account }. The admin approves xdr with their passkey, sends it through POST /transactions/relay with the header, then confirms. Errors return { error: { code, message } }, with codes such as NOT_A_MEMBER, NOT_ALLOWED, LAST_ADMIN, CHANGE_IN_PROGRESS, INVITE_EXPIRED and NOT_CONFIRMED.
GET /transactions/:chain/:hash
{ chain, state, hash, error? }, state one of PREPARED, AWAITING_SIGNATURE, SUBMITTED, CONFIRMED, FAILED.
PreparedTransaction
{
"chain": "stellar-testnet",
"family": "stellar",
"label": "Buy protection",
"payload": { "kind": "stellar", "networkPassphrase": "Test SDF Network ; September 2015", "xdr": "AAAA..." }
}
For EVM chains, payload is { kind: "evm", chainId, to, data, value }.