GET endpoint, but you should never have to.
Receiving works identically for custodial and non-custodial wallets. The deposit address is the wallet address either way. Detection and settlement are the same, and the balance lands in the same place. Custody only changes who controls the keys when funds leave — see the Non-Custodial Payout Lifecycle. Inbound, there is no difference.
Virtual Accounts are fiat-only. Crypto never credits a Virtual Account — an inbound deposit always credits the destination wallet. Funding with dollars over a bank rail is a different story: see the Money Movement Lifecycle and Virtual Accounts. Do not look for crypto in a Virtual Account. It will not be there.
Prerequisites
- An onboarded customer. See Onboard a Customer.
- The crypto wallets feature active on that customer.
- A webhook endpoint subscribed to the
crypto_wallet.*andtransaction.*events. See Webhooks.
The journey at a glance
ethereum, base, polygon, solana, tron. Amounts use the Money shape. Echo what Conduit sends you. Never round-trip an amount through a float.
Step 1 — Provision a wallet with a usable address
State: no wallet, or a wallet whose address is still null
A deposit needs somewhere to land. Create a wallet on the chain you want to receive on:The wallet (id prefix
wlt_) is created immediately, but its address is null while it provisions. Conduit assigns the address when provisioning finishes. There is no separate “generate deposit address” call. The address is a property of the wallet. A wallet without an address cannot receive anything.Advance: wait for provisioning to finish
Provisioning runs in the background. There is no call to make. You wait for one webhook.For non-custodial wallets, provisioning also depends on the customer’s signers enrolling. The Non-Custodial Payout Lifecycle covers that branch. Whether custodial or non-custodial, the same event tells you the address is live.
Step 2 — Share the address with the sender
State: the wallet has a populated address
The wallet’s
address field is the deposit address. There is nothing to generate, register, or activate. Hand that one string to whoever is sending you crypto, along with the chain. An address is only valid on its own chain.Advance: send the address out of band, then wait
Give the sender the
address and the chain. From here there is nothing to call. There is no API call to start a deposit — like the fiat funding story, you do not tell Conduit a deposit is coming. Conduit watches the chain and opens the deposit when funds arrive.One address per wallet, reusable for every deposit on that chain. You do not need a fresh address per payment. To receive on a different chain, create another wallet for it (Step 1).
Step 3 — Funds arrive and Conduit opens a deposit
State: funds confirmed on-chain, deposit pending
When the sender’s transfer confirms on-chain, Conduit detects it and opens a deposit transaction in status
pending. The credited-but-not-final amount appears in the wallet’s balances[] under pending.Advance: nothing — react to the webhook
There is nothing to do. Listen for the deposit event and reconcile it against your records.
- The source address is unregistered → the deposit parks at
transaction.awaiting_sender_information; submit sender information before the deadline, or it fails withSENDER_INFO_TIMEOUT. See SENDER_INFO_TIMEOUT. - The deposit is reversed or returned before it is credited →
transaction.failedwithfailureCode: RETURNED_BY_SENDER. See RETURNED_BY_SENDER. - A compliance review parks or holds the deposit →
transaction.failedwithfailureCode: COMPLIANCE_HOLD. See COMPLIANCE_HOLD. - The source is sanctioned →
transaction.failedwithfailureCode: AML_SANCTIONED. See AML rejections.
Step 4 — The deposit settles and the balance is credited
State: completed
Once the deposit clears, it settles. The amount moves out of
pending and into available on the wallet’s matching per-asset balance. The deposit transaction is now terminal.Step 5 — Read the balance back
State: funds are credited and spendable
The deposit lands on the wallet’s
On detection (Step 3) the amount sits in
balances[], one entry per asset. Each entry carries three buckets:| Bucket | Meaning |
|---|---|
available | Spendable now — what a payout can draw on. |
pending | Detected but not yet settled; not spendable. |
frozen | Held by a compliance action; not spendable. |
pending. On settlement (Step 4) it moves to available. A rejected or held deposit moves to frozen.Spend against
available only. The balance lands on the wallet, never on a Virtual Account — Virtual Accounts hold fiat. To send the received crypto back out, follow the Non-Custodial Payout Lifecycle, or initiate a custodial payout the same way.Terminal state
An inbound deposit stops at one of two terminal states.| Terminal status | Webhook | Meaning |
|---|---|---|
completed | transaction.completed | Funds settled and the amount is in available. The on-chain txHash is on the external_crypto side. The journey is done. |
failed | transaction.failed | The deposit could not be credited. Branch on failureCode — RETURNED_BY_SENDER, COMPLIANCE_HOLD, AML_SANCTIONED, or SENDER_INFO_TIMEOUT. When failureCode is absent the cause isn’t actionable — contact support. |
Where to go next
- Crypto Wallets — the wallet resource, custody models, and key rotation
- Non-Custodial Wallets — co-signing outbound transfers
- Non-Custodial Payout Lifecycle — sending received crypto back out
- Money Movement Lifecycle — the fiat-funding twin of this story
- Webhooks — subscribe to
crypto_wallet.completedandtransaction.*