- Most teams create one sub-account per merchant or segment. Then USDC balances and activity stay easy to trace in your books and in Circle reports.
- Every setup also includes a main wallet. USDC can live in the main wallet only, in sub-accounts only, or across both, depending on how you fund and pay out.
Wallet structure and typical flows
The following figure is a simplified model of a Managed Payments integration with sub-accounts. Circle enables only the paths that your setup and agreement support. Solid arrows are typical funding, receive, and payout paths, including payouts funded from the main wallet. Dotted arrows are optional paths your setup may use, such as a line of credit into the main wallet or moving USDC to a sub-account before payout.Accounts API
If you use the direct onboarding model, Circle handles the creation of
sub-accounts for you. Submit end-merchant KYB through the Partner Onboarding
API reference, and
Circle creates sub-accounts on your behalf after approval.
- Create a managed payments intermediary account when you add a merchant sub-account in the intermediary onboarding model.
- List accounts to page through sub-accounts and see each one’s balances and metadata.
- Get an account to
load one sub-account’s stablecoin account by
accountId, including balances and metadata.
accountId and a walletId. Both IDs point to the
same sub-account. The accountId names the stablecoin account record. The
walletId names the wallet that holds the account’s USDC balance. API requests
and responses use one or both, depending on the endpoint.
Circle grants role-based API access when you onboard. The endpoints your API
keys can call depend on the roles set for your account.
In the intermediary model, you call the
create account
endpoint after each merchant is approved. In the direct model, Circle provisions
sub-accounts during onboarding. In both cases, you reference the same
accountId values for wires, payouts, and payins.
Sub-account lifecycle
Use a sub-account’sstatus to determine whether it can process activity:
pending: Circle is creating the sub-account, but it isn’t operational yet.active: The sub-account can process supported activity.rejected: Circle rejected the sub-account creation request, and the sub-account can’t be used.archived: The sub-account is retired and excluded from account listings by default. Read requests still work, but most requests that change the account are blocked.
status=archived query parameter.
Archiving doesn’t permanently close a sub-account. An incoming deposit to an
existing deposit address or wire instruction automatically returns the
sub-account to active status. After you archive a sub-account, stop sending
funds to its existing deposit details if you intend to keep it retired.
Funding and pooled balances
Depending on your setup, USDC can be funded and spent across the main wallet and sub-accounts in several ways:- Wires can credit one sub-account so that merchant’s USDC sits in its own balance. Use the Wires API for bank accounts and wire instructions.
- If your setup allows it, you can mint to a shared main wallet instead. That pool can back steady, high-volume payout use cases.
- Some setups include a line of credit. USDC may land in the main wallet first; payouts can move funds to the correct sub-account before they go onchain. Terms follow your agreement with Circle.
- Payouts usually debit a sub-account balance. If your integration supports it, you can fund payouts from the main wallet instead of from each sub-account. That helps when you send a lot and don’t want USDC in every sub-account first. Use that path only when your setup supports it.
Payins and payouts
Handle payins, debits, and reconciliation per sub-account:- Payins (receiving USDC): Each sub-account can have a stable onchain address. Create a continuous payment intent so that each merchant or segment has a dedicated receive address.
- Payouts and withdrawals: Specify the
walletIdoraccountIdof the sub-account to debit when you create a payout.
The two money-out endpoints expect different
source.type tokens for the same
sub-account: create a
payout (POST /v1/payouts) requires source.type = wallet with the walletId, while
create a
withdrawal
(POST /v1/accounts/withdrawals) requires source.type = account with the
accountId.