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.
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
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
Webhook: crypto_wallet.completed
crypto_wallet.completed fires when provisioning finishes and the wallet is ready to receive funds. After it, the wallet’s address is populated and usable. Read it back at any time:Step 2 — Share the address with the sender
State: the wallet has a populated address
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
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.Step 3 — Funds arrive and Conduit opens a deposit
State: funds confirmed on-chain, deposit pending
pending. The credited-but-not-final amount appears in the wallet’s balances[] under pending.Advance: nothing — react to the webhook
Webhook: transaction.created
transaction.created fires with type: "deposit". The source is type: "external_crypto" and carries the sender’s address; the destination is type: "wallet" and carries the walletId, the wallet address, and the assetAmount ({ code, chain, amount }).type: "deposit_address" — a Conduit-provided funding
address. It carries address and assetAmount but no walletId, so
handle it as its own case rather than reading walletId off it. See
Deposit-Funded Orders.- A compliance review parks or holds the deposit →
transaction.failedwithfailureCode: compliance_hold. See COMPLIANCE_HOLD.
Step 4 — Clear an unregistered sender (required at or above the $3,000 Travel Rule threshold)
The under-threshold shortcut applies only to USD-pegged stablecoins (USDC, USDT). A stablecoin deposit **under 3,000 shortcut is valued at the stablecoin’s 1:1 USD peg; any deposit that is not a USD-pegged stablecoin takes the sender-information path below regardless of amount. When this step applies, it is mandatory. A qualifying deposit (a stablecoin of $3,000 or more, or any non-pegged asset, from a sender Conduit hasn’t seen before) does not settle on its own. It parks: the amount sits inpending, is not credited to the wallet, and cannot be spent until you submit the sender’s details. Miss the deadline and the deposit fails for good — the funds are never usable. (A parked deposit can also still be held or rejected by AML review — see COMPLIANCE_HOLD.)
If the sender’s address is already registered — or the deposit is a stablecoin under $3,000 — this step does not happen; the deposit goes straight from Step 3 to settlement (Step 5).
State: deposit parked, awaiting sender information
pending and Conduit fires transaction.awaiting_sender_information. Nothing is credited while it is parked. The fields you act on are the sourceAddress you must register, the assetAmount, the deadlineAt, and the daysRemaining countdown — a 30-day window in live. The example below is abbreviated to those; see Webhooks for the complete payload.Advance: submit the sender's details before the deadline
pending until you do.register: true to also save the address so future deposits from it clear on their own; leave it out (or false) to clear only this deposit. See Registered Addresses for the full originator shape — it covers both individual and business senders. You can submit only once per deposit: a second submission for the same deposit returns 409.Outcome: the deposit resumes — or times out
transaction.failed with failureCode: sender_info_timeout, and the funds are never credited. See SENDER_INFO_TIMEOUT.Step 5 — The deposit settles and the balance is credited
State: completed
pending and
into available on the wallet’s matching per-asset balance. The deposit
transaction is now terminal.Webhook: transaction.completed
transaction.completed fires for the deposit. The on-chain settlement
reference, txHash, lives on the external_crypto side of the payload. The
public transaction status has moved pending → completed.Step 6 — Read the balance back
State: funds are credited and spendable
balances[], one entry per asset. Each entry carries three buckets:pending. On settlement (Step 5) it moves to available. A rejected or held deposit moves to frozen.Advance: read the wallet
available reflects the deposit before you spend it.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.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.*