This guide covers the full token swap flow: browsing available assets, finding valid swap routes, getting a quote, executing the swap, and monitoring the result.
Test swaps in the Sandbox at https://crypto-sandbox.yativo.com/api/. Sandbox swaps simulate the full flow with test assets.
Browse available swap assets
Retrieve the list of assets supported for swapping. Use this to populate asset selector UI in your app.curl -X GET https://crypto-api.yativo.com/api/swap/assets \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c3JfMDFIWVo..."
Response (excerpt):[
{
"assetId": "eth-usdc",
"symbol": "USDC",
"name": "USD Coin",
"chain": "ethereum",
"contractAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"decimals": 6,
"canSwapFrom": true,
"canSwapTo": true,
"logoUrl": "https://assets.yativo.com/tokens/usdc.png"
},
{
"assetId": "eth-weth",
"symbol": "ETH",
"name": "Ether",
"chain": "ethereum",
"contractAddress": null,
"decimals": 18,
"canSwapFrom": true,
"canSwapTo": true,
"logoUrl": "https://assets.yativo.com/tokens/eth.png"
}
]
Find valid swap routes
Retrieve the available routes for a given asset pair. Routes describe the path the swap will take (which DEXes or bridges are involved) and help you select the best option.curl -X GET "https://crypto-api.yativo.com/api/swap/routes?fromAsset=eth-usdc&toAsset=pol-usdc" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c3JfMDFIWVo..."
Response:[
{
"routeId": "rte_01J2KV3MNPQ7R4S5T6U7VRTE01",
"fromAsset": "eth-usdc",
"toAsset": "pol-usdc",
"protocol": "stargate",
"estimatedTimeSeconds": 180,
"estimatedFeeUsd": "2.40",
"tags": ["cross-chain", "bridge"]
},
{
"routeId": "rte_01J2KV3MNPQ7R4S5T6U7VRTE02",
"fromAsset": "eth-usdc",
"toAsset": "pol-usdc",
"protocol": "across",
"estimatedTimeSeconds": 60,
"estimatedFeeUsd": "3.10",
"tags": ["cross-chain", "fast"]
}
]
Get a quote
Request a precise quote for a specific amount. Quotes have a short expiry window — execute the swap before the quote expires.curl -X POST https://crypto-api.yativo.com/api/swap/quote \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c3JfMDFIWVo..." \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_01J2K9MNPQ3R4S5T6U7V8W9X0Y",
"fromAsset": "eth-usdc",
"toAsset": "pol-usdc",
"fromAmount": "500.00",
"routeId": "rte_01J2KV3MNPQ7R4S5T6U7VRTE01"
}'
Response:{
"quoteId": "qte_01J2KW3MNPQ7R4S5T6U7VQTE55",
"accountId": "acc_01J2K9MNPQ3R4S5T6U7V8W9X0Y",
"fromAsset": "eth-usdc",
"toAsset": "pol-usdc",
"fromAmount": "500.00",
"toAmount": "497.52",
"exchangeRate": "0.99504",
"fees": {
"protocolFee": "1.25",
"networkFee": "1.23",
"yativoFee": "0.00",
"totalFeeUsd": "2.48"
},
"routeId": "rte_01J2KV3MNPQ7R4S5T6U7VRTE01",
"protocol": "stargate",
"expiresAt": "2026-03-26T14:03:00Z",
"createdAt": "2026-03-26T14:00:00Z"
}
Quote expiry handling
Quotes are valid for 3 minutes by default. If a quote expires before execution, request a fresh one.async function getValidQuote(params: QuoteParams): Promise<Quote> {
const BUFFER_MS = 30000; // require at least 30s before expiry
let quote = await client.swap.getQuote(params);
const expiresIn = new Date(quote.expiresAt).getTime() - Date.now();
if (expiresIn < BUFFER_MS) {
// Refresh immediately
quote = await client.swap.getQuote(params);
}
return quote;
}
Execute the swap
Submit the swap using the quoteId. The quote must not have expired.curl -X POST https://crypto-api.yativo.com/api/swap/execute \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c3JfMDFIWVo..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: swap_qte55_exec_01" \
-d '{
"quoteId": "qte_01J2KW3MNPQ7R4S5T6U7VQTE55",
"accountId": "acc_01J2K9MNPQ3R4S5T6U7V8W9X0Y"
}'
Response:{
"swapId": "swp_01J2KX3MNPQ7R4S5T6U7VSWP33",
"accountId": "acc_01J2K9MNPQ3R4S5T6U7V8W9X0Y",
"quoteId": "qte_01J2KW3MNPQ7R4S5T6U7VQTE55",
"fromAsset": "eth-usdc",
"toAsset": "pol-usdc",
"fromAmount": "500.00",
"expectedToAmount": "497.52",
"status": "pending",
"initiatedAt": "2026-03-26T14:01:30Z"
}
Monitor swap status
Poll the swap history endpoint or listen for swap.completed / swap.failed webhooks.curl -X GET "https://crypto-api.yativo.com/api/swap/history?accountId=acc_01J2K9MNPQ3R4S5T6U7V8W9X0Y&swapId=swp_01J2KX3MNPQ7R4S5T6U7VSWP33" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c3JfMDFIWVo..."
Completed swap response:{
"swapId": "swp_01J2KX3MNPQ7R4S5T6U7VSWP33",
"accountId": "acc_01J2K9MNPQ3R4S5T6U7V8W9X0Y",
"fromAsset": "eth-usdc",
"toAsset": "pol-usdc",
"fromAmount": "500.00",
"expectedToAmount": "497.52",
"actualToAmount": "497.38",
"exchangeRate": "0.99476",
"fees": {
"protocolFee": "1.25",
"networkFee": "1.37",
"yativoFee": "0.00",
"totalFeeUsd": "2.62"
},
"status": "completed",
"txHashSource": "0x1a3c5e7f9b2d4f6a8c0e2g4h6j8k0m2n4p6r8s0t2u4v6w8x",
"txHashDestination": "0xabcdef1234567890abcdef1234567890abcdef12",
"initiatedAt": "2026-03-26T14:01:30Z",
"completedAt": "2026-03-26T14:04:52Z"
}
Swap statuses
| Status | Description |
|---|
pending | Swap initiated, not yet broadcast |
in_progress | On-chain, awaiting destination confirmation |
completed | Funds arrived in destination asset |
failed | Swap failed — check failureReason |
refunded | Swap failed after funds were sent; original asset refunded |
Fee Breakdown
Every quote response includes a fees object:
| Field | Description |
|---|
protocolFee | Fee charged by the underlying protocol (DEX/bridge) |
networkFee | Gas costs on source and destination chains |
yativoFee | Yativo platform fee (0% on most routes) |
totalFeeUsd | Sum of all fees in USD equivalent |
The actualToAmount in the completed swap may differ slightly from expectedToAmount in the quote due to slippage and real-time gas fluctuations.
Next Steps