Changelog
Dated, additive changes to the TCB API surface.
Changes within v1 are additive: new endpoints, new optional request fields,
new response fields. A breaking change would be a new path segment. See
Versioning.
2026-10-30 — Quote a payout or a conversion before you make it
You can now see what a payout or a conversion will cost before you commit. Quote it first, then name the quote on the call that moves the money: the payout is charged the quoted Sending fee, and the conversion executes at the quoted rate and commission. Quoting is optional. See Quote a payout first and Quote a conversion first.
Added
POST /payouts/quote: the payout's Sending fee, its total andexpiresAt(60 seconds), under aquoteId.POST /conversions/quote: the conversion's rate, its commission, what it would credit (receiveAmount) andexpiresAt(the venue's own quote window, never more than 60 seconds), under aquoteId.quoteId, optional, onPOST /payoutsandPOST /conversions. A quote executes once, beforeexpiresAt, for the request it priced.commissionon the conversion object:{ amount, currency }, the commission the conversion was charged.nulluntil it settles, and on a conversion charged none.networkFeeon the conversion object and the conversion quote. Alwaysnull: TCB covers any network cost of a conversion and never charges it.requiresApprovalon the payout quote:truefor a first payment to a destination above your organisation's own first-send cap, which the payout itself refuses. A quote records nothing against the destination.- A quoted conversion fills at the quoted rate or better and is charged at most
the quoted commission; when the market has moved against the quote it is
refused with
QUOTE_TERMS_CHANGEDinstead. - Error codes
QUOTE_NOT_FOUND,QUOTE_EXPIRED,QUOTE_ALREADY_USED,QUOTE_MISMATCH,QUOTE_TERMS_CHANGEDandCONVERSION_RESULT_UNREADABLE. See Errors.
2026-10-30 — How a sub-client is held
Each sub-client holds its own account with TCB, in its own name. You collect the identity information and TCB accepts it. You instruct on the sub-client's behalf. The pages that describe sub-clients now say so. No endpoint, field or behaviour changed.
2026-10-27 — A payout pays the Sending fee for its rail
A payout now pays the Sending fee for the rail it travels, the same per-rail
fee a payment sent from the TCB app pays: on top of amount, in the payout's
currency, from the same source account. It is refunded with the payout. See
The Sending fee.
Added
feeon the payout object:{ amount, currency }, the Sending fee charged with the payout.nullonly on a payout refused before anything was debited.SENDING_FEE_UNPRICEABLE(409): no Sending fee is configured for the rail the payout would travel. Nothing was charged and the key stays usable.
Changed
INSUFFICIENT_BALANCEonPOST /payoutsnow means the source account does not hold the amount plus its Sending fee;details.requiredanddetails.feesay what the payout needs.
2026-10-27 — Fiat amounts are held to the currency's minor unit
Changed
- Settlements now refuse a fiat amount finer than the currency's minor
unit with
400AMOUNT_PRECISION_EXCEEDEDanddetails.allowedDecimals, the same refusal deposits, withdrawals, payouts and conversions give. - The minor unit is the currency's own, not a flat 2, on withdrawals and payouts too: JPY and KRW take whole units only (0 decimal places), and BHD, KWD, OMR, JOD and TND take 3. See Amounts and scales.
2026-10-22 — A crypto account's balance shows what is in flight
Changed
balance.reservedon a crypto account now carries what a conversion or an outgoing payment from it holds back until it settles, andavailableistotalminus that. The shape is unchanged; a fiat account still answersreserved: "0".
2026-10-20 — Your custody wallet is created on your first deposit
Your first POST /deposits or POST /token-mints creates the TCB
custody wallet that holds your position, before anything is charged.
Added
PARTNER_WALLET_PROVISIONING_FAILED(503): the wallet could not be created just now. Nothing was charged and your idempotency key was not claimed: resend with the same key or a new one, parameters unchanged or not.
2026-10-12 — The tokenised deposit chain, one step at a time
A vault deposit mints tcbUSD from your fiat and puts it into the vault; a vault withdrawal takes it back out and redeems it to fiat. Each of those steps is now a call of its own, so you can hold tcbUSD between them and queue a redemption the vault cannot pay right now. See Tokenised deposits, step by step.
Added
POST /token-mints(scopevault:deposit): debit a fiat account and mint the same amount of tcbUSD, booked to a sub-account.POST /token-redemptions(scopevault:withdraw): burn tcbUSD booked to a sub-account and credit the same amount of fiat.POST /share-subscriptions(scopevault:deposit): put tcbUSD booked to a sub-account into the vault; the shares are booked to the same sub-account.POST /share-redemptions(scopevault:withdraw): redeem shares for tcbUSD, paid at once and booked to the sub-account.POST /share-redemption-requestsandPOST /share-redemption-requests/{id}/cancel(scopevault:withdraw): queue a redemption in the vault's queue, and cancel what has not been paid.- A fetch and a paginated list for each step (scope
transaction:read):GET /token-mints,GET /token-redemptions,GET /share-subscriptions,GET /share-redemptions,GET /share-redemption-requests, each with its/{id}. GET /positions/tokens(scopeposition:read): your tcbUSD per sub-account — held, reserved and available — with the balance of the wallet that holds it.- Twelve webhook event types —
token_mint.settled/.failed,token_redemption.settled/.failed,share_subscription.settled/.failed,share_redemption.settled/.failed, andshare_redemption_request.queued/.settled/.cancelled/.failed— and the five resource types they point at. - The step error codes, and two new money caps,
TOKEN_MINT_CAP_EXCEEDEDandTOKEN_REDEMPTION_CAP_EXCEEDED. A vault subscription counts against your deposit cap and a vault redemption against your withdrawal cap. See Errors.
Changed
- The disclosure carried by every response and page is now version
2026-10-12. Its custody item now covers tcbUSD as well as vault shares: both are held in the one TCB wallet assigned to you, you hold no keys and move them only through this API, and each sub-account's shares and tcbUSD are book entries against what that wallet holds.
Unchanged, and worth saying
POST /depositsandPOST /withdrawalsbehave exactly as before, and remain the way to move fiat into and out of a vault in one call.
2026-10-10 — A payout may be held for review
TCB reviews some payments before they go out, from the app and from the API
alike. A payout that is flagged is debited and held: it reports the new
status HELD_FOR_REVIEW until TCB releases it (it continues to PROCESSING)
or declines it (it ends FAILED, the debit refunded). See
A payout may be held for review.
Added
HELD_FOR_REVIEWin the payoutstatusenum.payout.heldandpayout.releasedwebhook event types.
2026-10-10 — A deposit says when TCB has paused issuing the token
TCB can now stop issuing a token without a deployment — for a problem on the chain, in the mint path, or with the fiat behind the tokens. While it is stopped, a deposit that would mint that token is refused and says so. Nothing is charged, and withdrawals and redemptions are not affected. See Errors and Handle the errors.
Added
409 TOKEN_ISSUANCE_PAUSEDonPOST /deposits.details.idempotencyKeySpentisfalsewhen the deposit was refused up front, nothing was recorded and the same key stays usable;truewhen the pause landed while the deposit was executing, which leaves that deposit terminalFAILEDand needs a new key for the next attempt. Submitting again while the pause stands is refused again, so do not retry in a loop — contact TCB.
2026-10-09 — The position carries the rate the vault pays
GET /positions now returns the annual rate the vault pays, read on-chain,
in place of a rate derived from the observed share price. See
The share price and the rate.
Added
rateonGET /positions:apyBps(net of fees),asOf,stale,effectiveFrom,pendingChange,nextChangeandunavailableReason.
Removed
netApyBpsandbasisare gone fromGET /positions. To derive the rate a position has realised, useGET /positions/share-price-history, which is unchanged. This is a one-off exception to the additive-only rule forv1, made while the API is a testnet pilot.
2026-10-09 — A same-day deposit no longer moves what a position has earned
Fixed
currentValueonGET /positions(and theearnedLifetimeandearnedUnrealisedfigures built on it): a deposit settled after the latest share-price observation was valued at that earlier price, so the position showed a small gain or loss the moment it settled.currentValueis now the position at the latest observed share price, plus movements since that observation at their own amounts. A withdrawal since the observation leaves the remaining shares at the observed price. No field was added or removed. See Positions & accrual.
2026-10-08 — What your vault position has earned
The position now says what each sub-account has earned, valued at an observed share price you can verify. You can also list your vault deposits and withdrawals, and read the share price day by day. See Positions & accrual and List your deposits and withdrawals.
Added
shares.mintedon a deposit (POST /deposits, its replay andGET /deposits/{id}): the vault shares the deposit received, the same figure asshareson the deposit list.nullunless the deposit has settled.GET /depositsandGET /withdrawals: paginated lists, each row on one status set (QUEUED,PROCESSING,CREDIT_PENDING,COMPLETED,FAILED,REFUNDED,CANCELLED). Withdrawals carryrequestedAmount,creditedAmountandestimatedAvailableAt(set only for a queued withdrawal; vault withdrawals execute immediately, so it isnull).GET /positions/share-price-history: the vault's share price for each day, with the chain block and time it was observed. A day that was not observed isnull.- On
GET /positions:sharePrice(withasOfBlockandasOfAt),netApyBps(net of fees) and itsbasis.- In every
accrual:deposited,withdrawn,earnedLifetime,earnedUnrealised,earnedRealisedandnotObserved.earnedPeriodis filled when you send the new optionalperiodFromandperiodTo.
Changed
accrualis always present. A figure that cannot be observed isnullwith its reason innotObserved. A failed read now fails the request with503 CHAIN_UNAVAILABLE. It is no longer reported as anaccrualofnull.currentValueis the settled position at the latest observed share price shown insharePrice. When that observation is more than two days old the figures stay andsharePrice.staleistrue.- A sub-account whose records disagree (
EVIDENCE_INCONSISTENT), or that has more than 5,000 ledger entries (HISTORY_TOO_LONG), has its earned figures withheld; the rest of the report is served.
Removed
gross,netandresellCutare gone fromaccrualonGET /positions.earnedLifetimereplacesgrossandnet, which it always equalled;resellCutwas always"0". This is a one-off exception to the additive-only rule forv1, made while the API is a testnet pilot.
2026-09-24 — Crypto capabilities for sub-clients
Two new capability flags say whether an owner may hold and send crypto. A sub-client follows you by default, and TCB can set either flag for one sub-client. See Read what a sub-client may do.
Added
holdCryptoandsendCryptoin everycapabilitiesobject — on a sub-client'sverification.capabilitiesand on every account. On your own accounts they aretruewhen you hold crypto (your KYC is approved and you have an active crypto account). On a sub-client they take the same value by default and, like every flag, arefalseuntil it isVERIFIED.
Changed
- Opening a crypto network while acting as a sub-client now needs its
holdCrypto; without it the request is refused with409 SUB_CLIENT_CAPABILITY_UNAVAILABLE.
2026-09-24 — Crypto networks for sub-clients
A sub-client holds one crypto account. A network is opened in it from the TCB app while acting as the sub-client, and gets the sub-client's own deposit address. Every EVM network the sub-client opens shows the same address. Deposits to it follow the rules of your own crypto deposit addresses. See Crypto deposits.
Added
crypto_deposit.creditednow also fires for a credit on a sub-client's network. It is delivered to your endpoint and names the sub-client, whosex-on-behalf-ofthe fetch needs.SUB_CLIENT_HAS_CRYPTO_BALANCE(409) onPOST /sub-clients/{id}/closewhile any of the sub-client's crypto accounts holds an asset. On a successful close the sub-client's crypto deposit addresses retire with its IBANs. See Errors.
2026-09-24 — Search, filters and totals on the sub-client list
See Read your registry.
Added
q,countryandtypequery parameters onGET /sub-clients: case-insensitive search across legal name, external ref and email; filter by ISO 3166-1 alpha-2 country; filter by sub-client kind.totalHeldUsd,lastActivityAtandcountryon every row ofGET /sub-clients— the sum of the sub-client's accounts priced in USD, its latest transaction, and its derived country. Present only on that call;GET /sub-clients/{id}and every write response are unchanged.
2026-09-24 — One IBAN per account, plus local details
Every currency account receives on the one IBAN of the account it belongs to, and carries local details for its currency where the currency has them. See The account tree.
Added
localRailson every account: details on the currency's domestic scheme (SEPA for EUR, Fedwire / ACH for USD, Faster Payments / CHAPS for GBP, SIC for CHF), each with its bank, numbers,paymentReferenceandactive. Empty for JPY and BHD, for a crypto account, and for accounts opened before these details existed.
Changed
ibanon a currency account is its account's IBAN, the same on every currency in that account; a payment on it lands in the currency account for the payment's currency.- Existing per-currency IBANs are retired. A currency account that had an
IBAN of its own moves onto its account's IBAN, and its old IBAN is retired.
Money that arrives on a retired IBAN is not credited to any account: TCB
holds it, and an operator releases it by hand. Give your payers the IBAN
ibannow shows. The move sendsaccount.iban.issuedfor the account's IBAN and no event for the retired one. POST /accounts/{id}/ibanreturns the account's IBAN every time.ACCOUNT_ALREADY_HAS_IBANis no longer returned.account.iban.issuedis sent once per IBAN, for the first account that shows it, not for every currency added.
2026-09-23 — One account per currency
An owner holds one account per currency. To hold the same currency separately, open another account: ask TCB to open one for you. See Open an account in a currency.
Changed
POST /accountsno longer opens a SUB beside the MAIN. It opens the owner's account incurrency(201, roleMAIN, with its IBAN) or, when the owner already holds that currency, returns that account unchanged (200).labelandexternalRefapply only to an account the call opens;requestIbanis accepted and ignored.OWNER_HAS_NO_MAIN_FOR_CURRENCYis no longer returned.- Existing SUB accounts are folded into the MAIN in the same currency: the
balance moves by an internal transfer with reference
FOLD-…, and the SUB is closed with its history kept. The fold sends no webhook; read the SUB's transfers orGET /accounts?role=SUBto see it.
2026-09-16 — Net with a counterparty
Two members that pay each other often can now offset instead of posting each movement gross. See Net with a counterparty.
Added
/netting/agreements— propose (one currency, your account under it), accept (naming yours), decline, end, list and read.positionon every read carries what you owe, what you are owed, the net, who owes it and whether you may cut./netting/agreements/{id}/obligationsand/netting/obligations/{id}— owe into the set, list, read and withdraw. An obligation reserves its full amount the moment it is submitted: available on this rail is balance minusACTIVEholds minusOPENobligations. Netting never extends credit.POST /netting/agreements/{id}/cut— the member that owes the net cuts. One ordinary settlement posts for the net (none when zero) and every open obligation is netted in the same transaction.403 NETTING_CUT_NOT_NET_PAYERfor the other side;409 SETTLEMENT_CONFLICTif the set moved under the cut, with nothing written.- Webhooks
settlement.netting.agreement.proposed|accepted|declined|ended,settlement.netting.obligation.created|withdrawnandsettlement.netting.cut; resource typessettlement_netting_agreement,settlement_netting_obligation,settlement_netting_cut. - Codes
NETTING_AGREEMENT_NOT_FOUND,NETTING_AGREEMENT_NOT_OPEN,NETTING_AGREEMENT_EXISTS,NETTING_NOT_YOURS,NETTING_INVALID,NETTING_HAS_OPEN_OBLIGATIONS,NETTING_OBLIGATION_NOT_FOUND,NETTING_OBLIGATION_NOT_OPEN,NETTING_CUT_NOT_NET_PAYER,NETTING_NOTHING_TO_CUT.
Changed
INSUFFICIENT_BALANCEon this rail now foldsOPENnetting obligations intoreservedbesideACTIVEholds. A member with no netting agreement sees no difference.
2026-09-16 — Convert what you receive
A member can now ask for everything it receives over the network to land in one currency. The settlement is unchanged — same-currency, final in the currency the sender chose — and the conversion happens on the receiver's own accounts after it commits. See Convert what you receive.
Added
inboundConversionCurrencyonGET/PUT /network/profile. Set it to a currency you hold an active fiat account in and every settlement paid to you in another currency is sold for it on arrival, priced as your conversions normally are.nullclears it. Naming a currency you cannot hold answers422 INBOUND_CONVERSION_CURRENCY_UNAVAILABLE.receipton every settlement read:{ amount, currency, conversionOrderId }on the receiver's read once its rule has filled,nulleverywhere else — including always on the sender's read. What the receiver does with money that is final and theirs is not the sender's to see.
Unchanged, and worth saying
- A conversion that cannot be priced is not retried on a clock. The funds stay in the currency they arrived in and the receiver is told.
- A return of funds lands in the currency it was sent.
2026-09-16 — Transfers move fiat, and name the state of a blocked account
POST /transfers is a fiat rail: it moves fiat between two accounts in your
tree, in one currency, on TCB's ledger. A crypto balance is not moved by a
ledger entry — it moves on-chain — so naming a crypto account on either side
is now refused instead of posting. A leg that is unusable for a reason other
than closure now says so in its own code. See
Move money inside your tree.
Changed
- A crypto account on either side of
POST /transfersis refused with400 TRANSFER_ASSET_NOT_SUPPORTED. Before this date a crypto-to-crypto pair inside your tree was accepted and posted as a ledger entry, which is not how a chain balance moves: the ledger figure and the chain could then disagree. Fiat-to-fiat in one currency is unchanged — including every transfer between your fiat accounts and your sub-clients'. To move crypto, send it on-chain.details.accountIdanddetails.accountTypename the offending side.
Added
409 ACCOUNT_NOT_ACTIVEanswers a transfer naming an account that is neither active nor closed — today that means frozen.409 ACCOUNT_CLOSEDnow means what it says: the account is closed, which is irreversible. Before this date both states answeredACCOUNT_CLOSED, which sent you to the wrong remedy for a state that is lifted rather than permanent. Both codes carrydetails.status, and that is the field to key on: a state added to the enum later reaches you in a field you already read rather than as a code you have never seen. See Errors.
2026-09-14 — Choose who may pay you
The CONNECTED_ONLY receive policy now works. A member on it accepts
settlements only from the senders on its own connections list; everyone
else is still refused with 422 RECEIVE_POLICY_REFUSED. See
Choose who may pay you.
Added
GET /network/connections,POST /network/connectionsandDELETE /network/connections/{memberClientAccountId}list, add and remove the members allowed to pay you. Receiver-owned: nothing is asked of the member you add.connectedonGET /network/resolve: whether you are on that member's list, so a sender learns before paying whetherCONNECTED_ONLYwould refuse it.
Changed
RECEIVE_POLICY_REFUSEDis no longer unconditional for aCONNECTED_ONLYreceiver: a listed sender is accepted. Two new codes,422 CONNECTION_INVALIDand404 CONNECTION_NOT_FOUND, belong to the list itself.
2026-09-14 — Settlements with other TCB customers
Instant, same-currency payments to another TCB customer, settled directly on TCB's own ledger with no external rail — final on the response, and free. See the Settlements guide.
Added
POST /settlementssettles to another network member — name the account to debit and exactly one ofresolveToken,instrumentIdortoAccountId— andGET /settlementsandGET /settlements/{id}list and fetch settlements, scoped to the acting node. See Settle and Read a settlement.GET /network/resolveconfirms who a handle or TCB IBAN belongs to before you pay them, with a verdict on the name you supplied, andGET /network/searchis a bounded prefix search over members who opted into the directory. See Confirm who you are paying and Search the directory.GET /network/profileandPUT /network/profileread and set how you are addressed on the network: your handle (set once), whether you appear in directory search, your receive policy and your trading-name aliases. See Choose how you are paid.POST /settlement-requestsasks another member to pay you, withGET /settlement-requests,GET /settlement-requests/{id},POST /settlement-requests/{id}/approve,POST /settlement-requests/{id}/declineandPOST /settlement-requests/{id}/cancelto list, fetch, pay, refuse and withdraw one. See Ask to be paid.POST /settlement-holdsreserves funds against a named member without moving anything, withGET /settlement-holds,GET /settlement-holds/{id},POST /settlement-holds/{id}/releaseandPOST /settlement-holds/{id}/cancelto list, fetch, settle and cancel one. See Reserve before you pay.POST /settlements/{id}/return-requestasks the receiver of a completed settlement to send the money back, withGET /settlement-returns,GET /settlement-returns/{id},POST /settlement-returns/{id}/accept,POST /settlement-returns/{id}/declineandPOST /settlement-returns/{id}/cancelto list, fetch, accept, decline and withdraw one; accepting books a linked reversing settlement. See Ask for money back.- Eleven new webhook events:
settlement.settled,settlement.reversed,settlement.request.created,settlement.request.approved,settlement.request.declined,settlement.hold.created,settlement.hold.released,settlement.hold.cancelled,settlement.return.requested,settlement.return.acceptedandsettlement.return.declined. - Three new scopes are in use:
settlement:readon every read, including resolve and directory search;settlement:manageonPUT /network/profileand on creating, declining or cancelling a request, placing or cancelling a hold, and raising, declining or cancelling a return;settlement:executeon the calls that move money —POST /settlements, approving a request, releasing a hold and accepting a return. - A settlement names what it is linked to.
settlementRequestIdis the request it paid,settlementHoldIdis the hold whose release booked it, andsettlementReturnIdis the return whose acceptance booked the reversal — on both the reversed settlement and the reversing one — or, while the settlement isCOMPLETEDand not itself a reversal, the return request open on it.reversedByIdis the settlement that reversed this one, present wheneverstatusisREVERSED.reversalOfId, set only on a reversing leg, is the settlement it reverses. Each isnullwhen nothing is attached. - Raising a return can answer
409 SETTLEMENT_CONFLICT: a concurrent change to the same settlement; nothing was written, retry the request.
Documentation
- The Roadmap no longer lists this. Banking as a service and the overview now link the Settlements guide.
2026-09-10 — Crypto accounts appear in GET /accounts
GET /accounts was silently excluding every account funded by a crypto
deposit address: it
was reachable and fully usable at GET /accounts/{id}, but never listed. See
Accounts.
Fixed
GET /accountsnow lists every account you hold, fiat and crypto alike.?currency=USDC(or any other asset you hold) now returns it too — before this date it returned an empty page for a currency you actually held. Nothing else about the endpoint changed: pagination,role,status, and the response shape are the same for every account it returns.
Known
- A multi-asset container account is not listed. Where your onboarding
provisioned them, your tree also holds a pair of container accounts. They
carry no currency of their own and hold nothing directly — each asset sits
beneath them — so
GET /accountsleaves them out rather than reporting them as an account with no currency and a zero balance.GET /accounts/{id}still returns one if you name it, and reporting what sits beneath it is a filed follow-up. The accounts a deposit address funds are listed in full, so what you reconcile against those is unaffected.
2026-09-08 — Statements
Monthly, immutable statements of your sub-account ledger. See the Statements guide.
Added
GET /statementsissues (on first request) or lists the monthly statements for your sub-account ledger, keyed on a closed calendar month.GET /statements/{id}fetches one statement as JSON, or astext/csvwith?format=csv.
2026-09-07 — Documentation
The pages are regrouped around the two halves of the API — banking as a service and yield as a service. No route, field, error code or webhook changed.
Documentation
- Two new pages describe the halves in full: Banking as a service — accounts and IBANs, money in, money moved, money out — and Yield as a service — fiat placed into a curated vault and held as a position. Each carries its own capability table, flow diagram, step-by-step routes and money map.
- The overview is lighter. It points at the two pillar pages, keeps the capability summary, and leaves the flows and the step tables to them.
- Core concepts on the overview grows from three entries to seven, grouped by pillar: sub-clients and verification level, accounts and IBANs, transfers and conversions, destinations and payouts, vault positions and sub-accounts, intents and idempotency, and webhooks and scopes.
- Pilot scope is now the Roadmap: what follows the pilot, in sequence, as a compact table of six capabilities with what each does today and what comes next — including settlement with other TCB customers, statements and exports, and approval policies over the API. What the API does today lives on the two pillar pages instead, and the stated-direction list is dropped.
- The diagrams are redrawn. The object model in How it works now separates your account tree from your vault ledger, and the four state ladders in The money lifecycle read left to right with every arrow coloured by where it lands, so the differences between the flows are visible at a glance.
- The vault guide is now Vault deposits and withdrawals, and the reference groups it documents read Vault deposits and Vault withdrawals, so the vault leg is not read as a deposit held at a bank. The routes are unchanged.
- Where TCB describes client-money accounts, How it works now says which objects those are: the sub-client and the accounts under it. The API uses the word sub-client everywhere.
- Payouts are added to the money map in How it works, and Environments now states what is real for crypto deposits and for payouts.
2026-09-06 — Payouts
The pay half of third-party payouts. See the Payouts guide.
Added
POST /payoutspays a registered destination from a fiat account you control, andGET /payouts/{id}fetches one in its current state.- Scope
payment:executeis now in use, onPOST /payouts. - Three new webhook events:
payout.settled,payout.failedandpayout.returned. - New error codes:
PAYOUT_RAIL_NOT_AVAILABLE,PAYOUT_CAP_EXCEEDED,DESTINATION_NOT_USABLE,DESTINATION_BLOCKED,DESTINATION_KIND_NOT_SUPPORTED,DESTINATION_CURRENCY_MISMATCH,DESTINATION_INCOMPLETE,SCREENING_UNAVAILABLE,PAYOUT_FAILEDandPAYOUT_FAILED_PENDING_COMPENSATION. - The pilot scope page is updated: destinations and payouts are now one two-step capability, and what's next is paying a wallet destination and paying on behalf of a sub-client.
- As the standing disclosure above states, the fiat rail this call submits to is simulated: no real money moves.
2026-09-06 — Market-priced conversions
A conversion is now priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the request is refused and nothing is converted; TCB no longer prices a conversion from an internal table. See Conversions.
Changed
POST /conversionsrefuses with503 PRICING_UNAVAILABLEwhen no external venue returns a usable quote, instead of filling at a simulated rate.details.pairnames the pair, nothing is persisted and the idempotency key stays usable; retry later. This code replaces503 CONVERSION_NO_VENUE, which is no longer returned.rate.pricingModelisMARKETon every conversion settled from this date.SIMULATEDremains on conversions settled earlier and still means what it said: not a market rate.- The disclosure block's item on conversion rates now states that a
conversion is market-quoted or refused. The block's version is
2026-09-06.
2026-09-06 — Crypto-credited funds move onward
A balance credited by a crypto deposit can now be converted and, as fiat, deposited into a vault — two calls, each idempotent, each announced by its own webhook events. See Move credited funds onward.
Added
POST /conversionsaccepts the account your crypto deposit address credits assourceAccountId, and selects it when it is your only active account infromCurrency. Before this change the call answered that account with404 CONVERSION_ACCOUNT_NOT_FOUND.details.accountIdson409 CONVERSION_ACCOUNT_AMBIGUOUSnames every active account of yours in that currency when more than one matches an omittedsourceAccountIdortargetAccountId, so you can name the one you mean. TCB never picks between them.400 SOURCE_ACCOUNT_NOT_USABLEonPOST /depositsand400 DESTINATION_ACCOUNT_NOT_USABLEonPOST /withdrawalswhen the named account is the one your crypto deposit address credits: a vault takes and returns fiat, so convert first.details.accountIdnames the account. Both were404before this change. Nothing moves and the key stays usable.- The pilot scope page no longer lists onward movement of crypto-credited funds as a planned capability: it is live.
2026-09-05 — Money caps
TCB may set ceilings on your account's deposits, withdrawals and conversions, per currency and per flow. No ceiling applies unless TCB has configured one for your account, TCB tells you your ceilings when they are set, and there is no API to read or change them. See Money caps and, for conversions, Money caps.
Added
400 DEPOSIT_CAP_EXCEEDED,400 WITHDRAWAL_CAP_EXCEEDEDand400 CONVERSION_CAP_EXCEEDEDonPOST /deposits,POST /withdrawalsandPOST /conversions.details.capnames the ceiling (maxTicket,daily,monthly, ormaxOutstandingon deposits),details.limitits value anddetails.attemptedwhat the figure would have become. Nothing moves, and the idempotency key stays usable.
Fixed
POST /conversionsreturned a500on every request. It completes again.
2026-09-03 — Crypto deposits
Accept crypto at a TCB-issued deposit address. See the Crypto deposits guide.
POST /crypto-deposit-addressesissues your static deposit address for one asset on one chain — USDC on Arbitrum Sepolia in the pilot — and creates the account arrivals are credited to.- A confirmed on-chain transfer to it is credited to that account, with the same permanent, replay-safe identity as every other money movement: the transaction hash is the deposit's identity, and one transaction carrying several transfers credits each of them separately.
GET /crypto-depositsandGET /crypto-deposits/{id}read every recorded arrival, credited or not.crypto_deposit.creditedjoins the webhook catalogue — thin payload, fetched via the read routes, fired exactly once per credit.- An arrival the pilot does not accept is recorded and held, never credited and never silently dropped.
2026-09-03 — Payout destinations
The register half of third-party payouts. You can now register the destinations a future payout will name; the payout call itself is the immediately following capability and is not part of the API yet.
POST /beneficiariesregisters a destination — the payee and its bank account or wallet in one call. A destination is never usable at registration: it must clear screening, TCB approval, and a holding period first, and you have no way to shorten or skip any of them — only a TCB operator can release a hold early. See Destinations.GET /beneficiaries,GET /beneficiaries/{id}andDELETE /beneficiaries/{id}list, fetch and remove destinations. Removal keeps the record readable; nothing can be sent to a removed destination.- Two new webhook events:
beneficiary.activated(a destination became usable) andbeneficiary.blocked(screening or a TCB operator blocked it). - Two new scopes are in use:
payee:manageon the writes,payee:readon the reads. - New error codes:
BENEFICIARY_NOT_FOUND, andDUPLICATE_INSTRUMENTwhen you register details you already hold live. - The pilot scope page's third-party-payout exclusion is updated: the control half is live, and money leaving the bank via the API remains out of scope today.
2026-09-02 — Sub-client activation model
How a sub-client is held, what TCB needs before it can be activated, and what it may do before then.
- A sub-client is one of your end customers. Each sub-client holds its own account with TCB, in its own name. You collect the identity information and TCB accepts it. You instruct on the sub-client's behalf.
- Which onboarding model your firm gets is decided by TCB at your own
onboarding, on its assessment of your firm and a signed reliance agreement,
and
RELIANCEis granted per client account. Being regulated does not by itself qualify a firm for it. Where reliance is not available, end customers are onboarded directly by TCB, on a level that is not available yet. - An activation baseline is now published. For a person: legal name and aliases, permanent residential address, date of birth, nationality, passport number where applicable, national ID details, your own reference for the sub-client, the verification method, result, date and file reference, and the PEP, sanctions and risk results your screening produced. For a business: legal identity, existence, registration, ownership and control sufficient to identify every natural-person owner or controller at or above 20 %. TCB runs its own screening at activation as well. Supporting documents stay with you and must be producible without delay.
- No funds before
VERIFIED. Creating a sub-client reserves its identifier and its MAIN accounts and allocates each IBAN, but that coordinate is not active: it is not to be given out, is not entered into verification of payee, accepts no funds, holds no balance, and nothing can be paid from it or moved within your tree on the sub-client's behalf.NOT_STARTEDandREQUIREMENTS_DUEcarry no capabilities, andRESTRICTEDwithdraws them all — a restricted sub-client's balance is held, not returned. iban.activeon every coordinate says which state it is in:falseuntil its owner is verified,trueafterwards.- The attestation is evidence, not the activation switch.
verificationMethod,verificationResult,verifierRef,pepStatus,screeningResult,riskRatingandcddPerformedAtare all required on it. An attestation missing a required field, or sent for a sub-client whose mandatory identity data is outstanding, is refused with400 ATTESTATION_INCOMPLETEand nothing is recorded. TCB samples and tests the files behind attestations and may request documents at any time. - A
legalNamechange on a verified sub-client moves it back toREQUIREMENTS_DUEand deactivates its IBANs until it is verified again. The coordinates are not re-issued; they reactivate carrying the corrected payee name. - A vault sub-account attributes your own position to your funds, strategies or products. One that stands for one of your end customers must be linked to a registered sub-client; how that link is expressed in the API is being finalised.
2026-09-02 — v1 pilot
The first published version of the TCB API and of these docs.
Added
Identity and access
GET /me— identify the principal a key authenticates as, and read its scopes, environment tag and key prefix.- API keys with per-route scopes, and the
x-on-behalf-ofheader for executing a request as one of your sub-clients.
Sub-clients
POST /sub-clients,GET /sub-clients,GET /sub-clients/{id},PATCH /sub-clients/{id}— register and maintain your end customers.GET /sub-clients/{id}/identity— read the identity record you supplied.POST /sub-clients/{id}/attestations,GET /sub-clients/{id}/attestations— append and read the due diligence you attest to having performed.POST /sub-clients/{id}/currencies— add a currency, with its MAIN account and IBAN.POST /sub-clients/{id}/close.
Accounts
GET /accounts,GET /accounts/{id},POST /accounts— accounts under you or under one of your sub-clients, in MAIN and SUB roles.POST /accounts/{id}/iban— issue a payment coordinate.POST /accounts/{id}/close.
Vault deposits, withdrawals and conversions
POST /deposits,GET /deposits/{id}— fiat into a curated vault.POST /withdrawals,GET /withdrawals/{id}— fiat back out.POST /conversions,GET /conversions/{id}— convert one currency you hold into another.- A mandatory client idempotency key on every one of them, and a six-state lifecycle that names what happened to the money rather than a pipeline stage.
Positions
POST /sub-accounts,GET /sub-accounts— partition your position into named buckets, alongside thetcb:defaultbucket every client starts with.GET /positions— settled, reserved and available shares, in total and per sub-account, beside the share balance of the wallet TCB holds for you.
Transfers
POST /transfers,GET /transfers,GET /transfers/{id}— instant movement of fiat between accounts inside your own tree.
Webhooks
POST /webhooks,GET /webhooks,GET /webhooks/{id},DELETE /webhooks/{id}— register and manage endpoints.POST /webhooks/{id}/rotate-secret— rotate a signing secret with an overlap window during which both signatures verify.- Thin, signed payloads for the terminal money events and for sub-client, account and transfer changes.
Machine-readable specification
- openapi.partner.v1.json, published alongside these pages and authoritative where they disagree.
Documentation
- These docs replace the previous single-page reference. Guides, concepts and a generated per-operation API reference are now separate. The material that lived on the old front page has moved to Authentication, Conventions and Errors.