Skip to main content
CDP supports two kinds of fiat deposit destinations, depending on who owns the receiving account:
  • Entity Owned FIAT Deposit Destinations: for accounts owned directly by your entity, available on Fedwire or J.P. Morgan’s Kinexys Digital Payments network.
  • Customer Owned FIAT Deposit Destinations: for accounts owned by a KYC’d customer, available on ACH and Fedwire for US customers.
Each section below walks through the full journey in Sandbox: create the account, issue the fiat deposit destination, simulate an inbound deposit, and confirm it settles. Every step is a real API call so you can see exactly which endpoints your integration needs to hit.

Prerequisites

Install the CDP CLI (requires Node.js 22+):
Configure a Sandbox environment using your CDP Secret API Key JSON file from the CDP Portal. Point it at the Sandbox host so both the /platform/v2 APIs and the Sandbox-only simulation helper resolve:
Keep the API key secret. Never commit it to source control.
Sandbox does not connect to any bank. Deposit instructions returned here are placeholders for API testing, and deposits are triggered with a simulation helper, not real money movement. Do not send real funds to a Sandbox fiat deposit destination.

Entity Owned FIAT Deposit Destinations

Entity owned accounts can issue a fiat deposit destination on the Fedwire rail or the Kinexys rail (J.P. Morgan’s Kinexys Digital Payments network). Fedwire deposit destinations are ABA-routed, using a bank routing number and account number. Kinexys deposit destinations are BIC-routed instead: a Bank Identifier Code (BIC) addresses the account rather than an ABA routing number. Both rails also return a referenceCode that must be included in the payment memo to attribute the deposit to your account.

1. Create the entity-owned account

Create account without an owner. When owner is omitted, the account is owned by the entity making the request:
Entity owned accounts skip customer onboarding entirely: there’s no KYC’d customer, no capability requests, and no compliance.requesterIpAddress requirement, since these calls aren’t made on a customer’s behalf.

2. Issue the fiat deposit destination

Create deposit destination with type fiat and paymentRail set to fedwire or kinexys. Entity owned accounts only support these two rails:
Unlike the customer owned ACH flow, both entity owned rails activate immediately: status is active in the create response itself, there’s no pending provisioning step to poll for.

3. Share the deposit instructions

Once active, the fiat object holds the coordinates the depositor uses to send USD:
Always include the referenceCode in the payment memo/reference. Without it, the deposit may not be attributed to your account and the funds may not land.

4. Simulate an inbound deposit

paymentRail is required when simulating a deposit to a fiat destination, matching whichever rail you created the destination on:
After simulation, the same events fire as for the customer owned flow:
  • Webhook events fire: payments.transfers.processing then payments.transfers.completed
  • Transfer record is created: visible via List transfers
  • Balance is credited: this deposit destination has no target set, so funds land directly in the same account and currency (usd) rather than converting to another asset

5. Inspect the transfer and webhook

Get transfer to confirm settlement:
The resolved transfer’s source shape depends on the rail. Kinexys’s source reflects the BIC-routed rail: since Kinexys carries no sender name, source identifies the sending bank (for example JPMorgan Chase Bank, N.A.) rather than an individual or company name the way the ACH source object does (Step 8 of the customer owned flow, below). Fedwire’s source isn’t shown here. An entity owned Fedwire deposit is attributed by matching the incoming wire’s beneficiary against your entity’s legal name (the beneficiaryName from Step 3) rather than by capturing the sender’s identity, so there’s no sender detail to expose. The same payments.transfers.completed webhook fires for either rail.

6. Verify the balance update

List balances for account:

7. Withdraw to a linked payment method

Entity owned accounts settle outbound Fedwire and Kinexys payments through a payment method rather than a bank-detail target. List payment methods to find the linked one, filtering by rail:
Then create a transfer targeting it directly, with execute: true to settle in one call:
The completed transfer includes a payment_code in metadata, a settlement reference for the outbound wire. To validate a withdrawal without moving funds, set execute: false and validateOnly: true; this returns a quoted status without creating a transfer. See the Transfers Quickstart for the full payment method withdrawal walkthrough and the Transfers overview for fee quotes and travel rule requirements.

Customer Owned FIAT Deposit Destinations

Customer owned accounts can issue fiat deposit destinations on the ACH and Fedwire rail. With FIAT deposit destinations for customer owned accounts, you can provision a Virtual Account for your end users, powered by Coinbase and Citi.

1. Onboard a KYC’d customer

Create a customer with type individual, requesting the capabilities this flow needs: See the full capability set for every capability CDP supports. In Sandbox, the fullSsn value 000-00-0000 is a magic value that forces a deterministic approval, so the requested capabilities verify and become active without real PII.
For the full customer lifecycle (identity fields, Terms of Service, tax attestations, and the requirements each capability needs), see the Customers Quickstart.

2. Confirm the custodyFiat capability is active

Creating a fiat deposit destination requires the customer’s custodyFiat capability to be active. Verification is asynchronous; with the approval magic value it settles quickly. Poll with Get a customer:
In production, subscribe to the customers.capability.changed webhook rather than polling. If custodyFiat is not active, the create call in Step 4 returns 403 customer_not_authorized.

3. Create the customer’s account

Create account with the customer as owner. This is where deposited funds will land as USDC. Passing the customer ID as owner makes it customer-owned; customer-facing operations require the end-user’s IP on compliance.requesterIpAddress.

4. Issue the fiat deposit destination

Create deposit destination with type fiat for the account. For customer-owned accounts, this provisions a virtual bank account at Citi. This is a customer-facing operation, so it also requires the end-user’s IP on compliance.requesterIpAddress. Choose a target for the incoming funds: credit a CDP account, or route straight out on-chain to an external address as each deposit settles (useful for automated sweeps to a non-custodial address):
Set target.asset to usdc so incoming USD is converted and credited as USDC:
The rest of this guide continues with a deposit destination that credits an account. If you use the onchain address target instead, deposits forward automatically once the destination is active, without a separate transfer.
If custodyFiat is not active, this returns 403 with errorType: customer_not_authorized and the missing capability under unauthorizedCapabilities. Resolve it (Step 2) and retry.
The response status is pending: the banking partner (Citi in production) is still provisioning the account.

5. Wait for activation

Poll Get deposit destination until the fiat deposit destination is active. In production, the destination activates once Citi completes provisioning; Sandbox activates it without any bank interaction. Only then can it receive deposits.
No webhook fires for fiat deposit destination creation or the pending → active transition. You must poll GET /v2/deposit-destinations/{depositDestinationId} to confirm status is active before sharing deposit instructions or simulating a deposit.

6. Share the deposit instructions

Once active, the fiat object holds the bank coordinates the depositor uses to send USD: ACH and Fedwire are currently the publicly supported rails.
A fiat deposit destination can be funded by the customer themselves (the sender name must match the KYC’d customer).

7. Simulate a deposit

Because Sandbox is not connected to a bank, use the simulation endpoint to trigger an inbound deposit. paymentRail is required when simulating a deposit to a fiat destination (ach or fedwire). For a fiat destination, asset defaults to the destination’s currency (usd).
After simulation:
  • Webhook events fire: payments.transfers.processing then payments.transfers.completed
  • Transfer record is created: visible via List transfers
  • Balance is credited: the account receives USDC (converted 1:1 from USD)

8. Inspect the webhook payload

When the deposit settles, CDP fires a payments.transfers.completed webhook to your subscribed endpoint. The payload includes the transfer record, a reference back to the fiat deposit destination, and any metadata set on it.
This requires a webhook subscription; CDP has nowhere to deliver the event otherwise. See Create webhook subscription and Transfer Webhooks to set one up.
A payments.transfers.processing event fires earlier when the deposit is first detected. For most integrations, listening for completed is sufficient. If a deposit is returned, a payments.transfers.failed event fires with the reason.

9. Verify the balance update

Confirm the deposit credited to the account as USDC with List balances for account:

Move to production

To run either flow for real, switch the Sandbox base URL to the production base URL and use a production API key. In production there are no magic values (customer owned flows require the customer to complete real KYC), and fiat deposit destinations are provisioned at a banking partner.

Deposit Destinations overview

Crypto and fiat deposit destinations: concepts, rails, lifecycle, and who can send funds

Customers & KYC

Onboard and verify the customer that owns a customer owned fiat deposit destination

Payment Methods

Link and use external bank accounts, including Fedwire and Kinexys, as transfer targets

Transfers

Move funds out of an account to a wallet address, email, or payment method

Webhooks

Subscribe to real-time deposit event notifications

REST API reference

Full Deposit Destinations API reference