Deposit swaps
Ordinary deposits require your customer to send an asset Cheddar custodies. Deposit swaps remove that limit: your customer can send almost any token on almost any chain, and Cheddar credits their balance in USDC.
You request a swap, Cheddar returns a deposit address. Your customer sends the
origin token there. It is swapped and credited, and your existing
CUSTOMER_DEPOSIT webhook fires exactly as it does for a
normal deposit.
Deposit swaps must be enabled for your organization. Until then every call
returns 403. Contact the Cheddar team to switch it on.
This is not the Swap feature. That converts an asset you hold and pays out to a whitelisted address. Deposit swaps fund a customer balance from outside.
How it works
List accepted assets
Always pass assetId back verbatim. Never build one yourself — the format
belongs to the upstream provider and can change.
Create a swap
amount is atomic units — 0.005 ETH is 0.005 × 10^18. Decimals like
"0.005" are rejected.
What to show your customer
The deposit address — where they send. Single use; do not reuse it across swaps.
minAmountIn, not amountIn — this is the real floor. Anything at or above
it swaps; below it is refunded. Your slippage tolerance is applied to the input
side precisely so a customer sending from their own wallet does not fail for
being a fraction short.
The deadline — the deposit must arrive before this. Measured in days, not minutes, but read it from the response rather than assuming.
depositMemo, if it is not null, is REQUIRED. Some chains need a memo
alongside the address, and omitting it loses the funds permanently. Display it
as prominently as the address itself.
Refund address
refundTo must be valid on the origin chain. Cheddar validates the format
before anything is spent, so a malformed address fails immediately.
Cheddar cannot verify your customer actually controls that address — format validity is not ownership. Prefer an address from a connected wallet over free text. A valid address they do not own is an unrecoverable loss.
Idempotency
Use one idempotencyKey per swap you actually intend, not per HTTP attempt.
Retrying with the same key returns the same swap with existing: true and
spends no new quote.
Requesting a second swap for the same customer and origin asset also returns the existing one rather than issuing a new quote. If it is close to expiry it is replaced automatically, so you never receive an address about to stop working.
Track the outcome
Success is pushed, failure is pulled. A successful swap fires your existing
CUSTOMER_DEPOSIT webhook. A failed, refunded, or expired one fires nothing.
If you rely on webhooks alone, a refund is invisible to you and your customer
is left guessing — poll this endpoint until the status is terminal.
Poll every 30–60 seconds while non-terminal. Terminal statuses never change.
Amounts, slippage and fees
Three different “amount out” appear, and only one is a promise:
Show minAmountOut to customers. Promising the quote and delivering less is a
support ticket you created for yourself. Realized slippage is
(quotedAmountOut - actualAmountOut) / quotedAmountOut — typically a fraction
of the tolerance you requested.
Two fees are reported, and both are easy to misread:
withdrawFee— in the destination asset, and already deducted inside the quote. Do not subtract it a second time.refundFee— in the origin asset, charged only on a refund.
They are denominated in different assets, so never add them together.
Swaps below $10 of input are rejected: cross-chain costs would exceed what the customer receives.
USD figures in responses are display only. Never use them for accounting.