Custodial Wallets require a business account. This recipe assumes your platform is already onboarded with Custodial Wallets enabled. If you’re interested or want to check whether this fits your use case, get in touch and our team will follow up.
https://api.cdp.coinbase.com/platform for the SDK, or cdp env production for the CLI) and use a production API key.
Flow of funds

Prerequisites
- Your entity is onboarded (KYB’d) with Custodial Wallets enabled. See the Custodial Wallets overview.
- For delegated payouts, your originator terms of service must be accepted and passed on each payout (shown in Step 3). This is what authorizes Coinbase to convert and send on your behalf.
- The CDP CLI or TypeScript SDK installed and pointed at Sandbox. Both require Node.js 22 or later.
Account structure
Install and configure
- CDP CLI
- TypeScript SDK
Pick one path, the CDP CLI or the TypeScript SDK, and follow that tab in every step. Each CLI command runs on its own. The SDK snippets build up a single
main.ts file, so the complete runnable script is at the end under Run the SDK flow as scripts.Copying these commands: anything shown as a placeholder — values ending in
... (like account_...) or wrapped in <ANGLE_BRACKETS> — must be replaced with your real value before running. Use each code block’s copy button; if you paste through a rich-text editor (Google Docs, Notes), straight quotes " can turn into curly " and the shell will hang on a dquote> prompt.1. Create your treasury account
Your entity-owned USD account. Omitting an owner makes the account entity-owned.- CDP CLI
- TypeScript SDK
entity_:2. Fund the treasury with USD
In Sandbox, there are no real wires, so add a USD test balance in the Portal: Accounts → your treasury account → Edit test assets → set USD, then Save changes.
Edit test assets: set the treasury's USD balance (here, 100).

The treasury account funded with $100 USD (entity-owned).
3. Pay out USDC to a beneficiary’s wallet
This is a delegated payout: the source is your USD balance, the target is an onchain address receivingusdc, and fulfillmentMode: "delegated" tells Coinbase to convert the USD to USDC and send it onchain for you. Include compliance with your originator terms-of-service acceptance and the beneficiary’s details.
In Sandbox there’s no real recipient wallet, so use a reserved test address like
0x1111111111111111111111111111111111111111 (it settles as a success). In production, use the beneficiary’s real wallet address. The compliance.originator versionId is your entity’s current terms-of-service version, read from its requirements; Sandbox doesn’t validate it, so unlike other placeholders in this guide, you can leave <REQUIRED_TOS_VERSION_ID> as-is (or use any non-empty string) when testing.- CDP CLI
- TypeScript SDK
amount and asset are in usd (what you spend); the target asset is usdc (what the beneficiary receives). Coinbase handles the conversion. The CLI passes the JSON body to cdp transfers create on stdin (-), so the nested compliance block is sent exactly as written.4. Confirm the payout
The payout settles asynchronously; you get apayments.transfers.completed webhook when the USDC lands onchain. You can also poll it:
- CDP CLI
- TypeScript SDK
In Sandbox the payout settles immediately, so this check returns
completed. In production the first check usually shows quoted or processing; rely on the payments.transfers.completed webhook, or poll until the status reaches completed.
After the payout, the treasury's USD balance drops from $100 to $50.
Run the SDK flow as scripts
Run the SDK flow as scripts
The SDK snippets above build on one client and belong in a single file. Because funding the treasury (Step 2) happens in the Portal, run it as two scripts: create the account, fund it, then pay out. Save each as a Fund that account in the Portal (Step 2), then run Part 2.Part 2 — pay out and confirm (Steps 3 to 4). Paste the treasury account ID Part 1 printed.
.ts file and run it with npx tsx <file>.ts (Node 22 or later; tsx runs TypeScript directly, no build step).Part 1 — create the treasury (Step 1). Prints the account ID to fund.main.ts
main.ts
Good to know
- Delegated payout: with
fulfillmentMode: "delegated", Coinbase debits your USD, converts it to USDC, and sends it onchain. You fund only in USD and never custody stablecoins. - Originator terms of service must be accepted and passed in the
compliance.originatorblock. That acceptance is what authorizes Coinbase to run the delegated payout. Fetch the required version from the entityrequirements. - Reconciliation: attach
metadata(a reference or customer ID) to each payout, and query history withcdp transfers listor the Transfers API. - Idempotency: every SDK call passes an
idempotencyKey, so a retried request returns the same result instead of creating a duplicate payout. Thecdp transfers createCLI command has no idempotency option, so for production prefer the SDK (or the REST API, which accepts an idempotency key) for safe retries.
What to read next
Customers / KYC
Onboard the entity and customers behind these payouts
Transfers
All transfer types, rails, and lifecycle
Deposit Destinations
Fiat and crypto deposit destinations
Webhooks
React to payout status in production