Quote a payout before making it
Prices the payout you are about to make, without making it: the Sending fee for the rail it will travel, and what leaves your account in total. Nothing is charged and no idempotency key is needed. The request is checked exactly as the payout would be (your money caps, your balance against amount plus fee, the destination's current state, the rail), so a refusal here is the refusal the payout would get. The quote is held for 60 seconds (expiresAt). Name its quoteId on POST /payouts to be charged the quoted fee; the payout must repeat the quoted request (instrumentId, currency, amount, sourceAccountId and the x-on-behalf-of header) and can use the quote once. Quoting first is optional and recommended: it is how you see the fee before you commit. A quote reserves nothing: your balance, caps and the destination are checked again when you pay. Send x-on-behalf-of to quote a payout of one of your sub-clients' money.
Prices the payout you are about to make, without making it: the Sending fee for the rail it will travel, and what leaves your account in total. Nothing is charged and no idempotency key is needed. The request is checked exactly as the payout would be (your money caps, your balance against amount plus fee, the destination's current state, the rail), so a refusal here is the refusal the payout would get. The quote is held for 60 seconds (expiresAt). Name its quoteId on POST /payouts to be charged the quoted fee; the payout must repeat the quoted request (instrumentId, currency, amount, sourceAccountId and the x-on-behalf-of header) and can use the quote once. Quoting first is optional and recommended: it is how you see the fee before you commit. A quote reserves nothing: your balance, caps and the destination are checked again when you pay. Send x-on-behalf-of to quote a payout of one of your sub-clients' money.
Authorization
bearer In: header
Header Parameters
Act on behalf of one of your sub-clients. The value is that sub-client id, and the request then reads and writes that sub-client's own accounts and registry rows rather than yours. Omit it to act as yourself. A route that does not accept the header refuses it with 400 ON_BEHALF_OF_NOT_ALLOWED_HERE rather than ignoring it — that includes every vault route (deposits, withdrawals, conversions, sub-accounts, positions), the webhook registry, and POST /sub-clients, since a sub-client never has sub-clients of its own. An id that is not one of your sub-clients answers 404 ON_BEHALF_OF_NOT_FOUND; a closed one answers 409 ON_BEHALF_OF_SUB_CLIENT_CLOSED; and a key restricted to a subset of your sub-clients answers 403 ON_BEHALF_OF_NOT_ALLOWED_FOR_KEY for any node outside it.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
A payout to quote: the destination, the currency and amount, and the optional source account.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/api/partner/v1/payouts/quote" \ -H "Content-Type: application/json" \ -d '{ "amount": "1250.00", "currency": "EUR", "instrumentId": "1d7a9f42-6b05-4e83-a2c1-8f3b0d6e4c97", "sourceAccountId": "7e2a0c53-4d81-49b6-8f37-1a5c9e0b2d74" }'{ "data": { "amount": "1250", "currency": "EUR", "disclosure": { "items": [ "ENVIRONMENT_IS_TESTNET: The environment is a testnet (Arbitrum Sepolia). No mainnet deployment exists.", "YIELD_IS_SIMULATED: The vault rate is set administratively and the interest it produces is minted as fresh underlying, not earned. It does not represent a return generated by deployed capital.", "FIAT_RAILS_ARE_MOCKED: No real fiat movement occurs. Balances are ledger entries against a sandbox provider.", "CONVERSION_RATES_ARE_MARKET_QUOTED_OR_REFUSED: A conversion is priced only by an external venue that quotes independently of TCB. When no such venue can price the pair, the conversion is refused rather than priced from an internal table. Read rate.pricingModel on every conversion: MARKET is a venue quote; any other value is not a market rate and must not be presented as one.", "CONTRACTS_ARE_UNAUDITED: No audit has been performed. Mainnet is gated on a two-firm audit that has not been commissioned.", "CUSTODY_IS_TCB_SUBACCOUNT: Everything held for the client — its vault shares, and the tcbUSD it holds between the steps of the tokenised deposit chain — is held in TCB custody, in the one TCB wallet assigned to the client. The client holds no keys and moves those tokens only through this API; each sub-account's shares and tcbUSD are book entries against what that wallet holds.", "INTEGRATION_AGREEMENT_ONLY: Fees as published on the rate card; no yield share, no return commitment." ], "summary": "This is a pilot integration on a testnet. Nothing in this system earns anything: the yield is simulated and the fiat rails are mocked.", "version": "2026-10-27" }, "expiresAt": "2026-10-30T10:16:28.000Z", "fee": { "amount": "25", "currency": "EUR", "rail": "SEPA" }, "quoteId": "0b6f2d84-3c19-4e7a-9a52-6d1e8f4c7b30", "requiresApproval": false, "total": "1275" }, "success": true, "timestamp": "2026-09-02T10:15:30.000Z"}Pay a registered destination POST
Sends fiat from one of your accounts to a destination you registered and that has completed screening, TCB approval and its holding period. The request names the destination by instrumentId — there is no way to pass raw bank details. Before anything is charged the payout is checked against your money caps, your balance, and the destination's current state; it is checked again immediately before the money leaves. The payout pays the Sending fee for the rail it travels (the destination's rail), the same per-rail fee a payment sent from the TCB app pays: on top of amount, in the same currency, from the same source account, so the account must cover both. The response states it as fee. Money caps count amount alone. To see the fee before you pay, quote the payout first (POST /payouts/quote) and name the quoteId here: the payout is then charged the quoted fee. The fee is refunded with the payout whenever the payout is refunded or returned. The response is PROCESSING once the rail has accepted the payment; settlement arrives as the payout.settled webhook, or on GET /partner/v1/payouts/{id}. An idempotency key is MANDATORY: send it as the Idempotency-Key header or as the idempotencyKey body field. Replaying a key returns the same payout in its current state without paying again; reusing one with different parameters is rejected with IDEMPOTENCY_KEY_REUSED. Every response carries the pilot disclosure: the fiat rail is mocked, so no real money moves. Send x-on-behalf-of to pay with one of your sub-clients' money: the payment then leaves that sub-client's own account and carries its own name and account details as the sending party, never yours. The destination is still one from YOUR registry, and a destination you filed for a different sub-client is not payable from this one. The sub-client needs the sendExternal capability. The header is part of the payment: the same idempotency key with and without it is rejected as reused.
Fetch one payout by id GET
The payout in its CURRENT state, whatever that is — including a terminal failure, reported here as the object rather than as an error, and a return (RETURNED, with the re-credit) after settlement. This is the fetch half of the thin webhook payloads (a payout.* event carries only a resource pointer) and the poll surface the money errors point at. A payout you made for a sub-client is fetched by sending the same x-on-behalf-of header; its webhook carries that sub-client id so you know which one.