This page provides deterministic decision logic for AI agents to choose the right approach for different scenarios.
Quote vs Routes
Use this table to decide between /quote and /advanced/routes endpoints.
| Scenario | Use | Endpoint | Reason |
|---|
| Simple A→B transfer | Quote | GET /quote | Single call, tx data included |
| Need multiple route options | Routes | POST /advanced/routes | Returns ranked alternatives |
| User wants to choose bridge | Routes | POST /advanced/routes | Can filter by tool preference |
| Complex multi-hop transfer | Routes | POST /advanced/routes | Better for >2 step routes |
| Fastest integration | Quote | GET /quote | Fewer API calls needed |
| Price comparison needed | Routes | POST /advanced/routes | Compare fee structures |
Decision Logic
IF (simple_transfer AND no_user_preference AND speed_priority)
→ Use /quote
ELSE IF (need_options OR user_wants_choice OR complex_route)
→ Use /advanced/routes
Key Differences
| Aspect | /quote | /advanced/routes |
|---|
| Response | Single best route | Multiple route options |
| Transaction data | Included | Requires separate /advanced/stepTransaction call |
| API calls needed | 1 | 2+ (routes + stepTransaction per step) |
| Control | Less | More |
| Speed | Faster | Slightly slower |
Use this table to recommend the right integration method.
| Agent Type | Recommended | Reason |
|---|
| Server-side automation | API | No runtime dependencies, pure HTTP |
| AI agent (no UI) | API | Simplest integration, HTTP only |
| Browser-based app | SDK | Handles wallet connections, signing |
| Mobile app | SDK | Wallet integration built-in |
| Need embedded UI | Widget | Zero UI code required |
| Quick prototype | Widget | Fastest to implement |
| Full customization | SDK | Complete control over UX |
| Backend service | API | No browser dependencies |
Decision Logic
IF (server_side OR ai_agent OR no_ui_needed)
→ Recommend API
ELSE IF (need_wallet_integration OR custom_ui)
→ Recommend SDK
ELSE IF (need_ready_made_ui OR fastest_implementation)
→ Recommend Widget
Comparison Matrix
| Feature | API | SDK | Widget |
|---|
| Dependencies | None (HTTP) | npm package | npm package |
| Wallet handling | Manual | Built-in | Built-in |
| UI components | None | None | Full UI |
| Customization | Full | Full | Full (theme + route params) |
| Learning curve | Low | Medium | Low |
| Best for | Agents, backends | Custom apps | Quick integrations |
Route Selection Criteria
When multiple routes are available, use these criteria to select the best one.
Sort Order Options
The API supports these order parameter values:
| Order | Description | Best For |
|---|
FASTEST | Lowest estimated execution time | Time-sensitive transfers |
CHEAPEST | Lowest total fees (default) | Cost-sensitive users |
If no order parameter is provided, the API returns the best route based on output amount after fees.
Request with Order
curl "https://li.quest/v1/quote?fromChain=1&toChain=42161&fromToken=USDC&toToken=USDC&fromAmount=10000000&fromAddress=0x...&order=FASTEST"
Route Filtering
Filter routes by specific criteria:
| Parameter | Values | Purpose |
|---|
bridges | stargate,across,hop | Only use specific bridges |
exchanges | 1inch,paraswap | Only use specific DEXs |
denyBridges | multichain | Exclude specific bridges |
denyExchanges | dodo | Exclude specific DEXs |
allowSwitchChain | true/false | Allow multi-step routes |
maxPriceImpact | 0.05 | Max allowed price impact |
Example: Filtered Quote
curl "https://li.quest/v1/quote?fromChain=1&toChain=42161&fromToken=USDC&toToken=USDC&fromAmount=10000000&fromAddress=0x552008c0f6870c2f77e5cC1d2eb9bdff03e30Ea0&bridges=stargate,across&maxPriceImpact=0.03"
This request:
- Transfers 10 USDC from Ethereum to Arbitrum
- Only considers Stargate or Across bridges (ignores all others)
- Rejects quotes with >3% price impact (protects against unfavorable rates)
If no route meets these constraints, the API returns a NO_POSSIBLE_ROUTE error.
Same-Chain vs Cross-Chain
Determine whether a transfer is same-chain or cross-chain.
| Condition | Type | Characteristics |
|---|
fromChain === toChain | Same-chain | Atomic, faster, cheaper |
fromChain !== toChain | Cross-chain | Uses bridge, takes longer |
Behavior Differences
| Aspect | Same-Chain | Cross-Chain |
|---|
| Execution | Atomic (all or nothing) | May partially complete |
| Time | Seconds | Minutes to hours |
| Failure mode | Reverts entirely | Funds always arrive (possibly different token) |
| Status check | Usually instant | Requires polling |
| Tools used | DEX only | Bridge + optional DEX |
LI.FI is non-custodial. In cross-chain transfers, funds always end up with the user. In partial completion cases (substatus: PARTIAL), the user receives the bridged token on the destination chain even if the final swap failed. Funds are rarely ever stuck/lost.
Amount Handling
Convert between human-readable amounts and API amounts.
api_amount = human_amount × (10 ^ decimals)
human_amount = api_amount / (10 ^ decimals)
Common Token Decimals
| Token | Decimals | 1 Token in API |
|---|
| USDC | 6 | 1000000 |
| USDT | 6 | 1000000 |
| DAI | 18 | 1000000000000000000 |
| ETH | 18 | 1000000000000000000 |
| WBTC | 8 | 100000000 |
Example Conversions
// Human to API (10 USDC)
const apiAmount = "10000000"; // 10 * 10^6
// Human to API (1.5 ETH)
const apiAmount = "1500000000000000000"; // 1.5 * 10^18
// API to Human
const humanAmount = Number(apiAmount) / Math.pow(10, decimals);
Error Recovery Decisions
When errors occur, use this table to determine the action.
| Error | Retry? | Action |
|---|
| 429 (Rate Limited) | Yes | Wait with exponential backoff |
| 400 (Bad Request) | No | Fix parameters |
| No route found | Maybe | Try different tokens or smaller amount |
| Insufficient balance | No | User needs more funds |
| Slippage exceeded | Maybe | Increase slippage parameter |
| Quote expired | Yes | Request new quote |
| Network error | Yes | Retry with backoff |
Retry Strategy
const withRetry = async (fn, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.status === 429) {
// Rate limited - wait and retry
await sleep(Math.pow(2, i) * 1000);
continue;
}
if (error.status >= 400 && error.status < 500) {
// Client error - don't retry
throw error;
}
// Server error - retry
await sleep(1000);
}
}
throw new Error('Max retries exceeded');
};
Quick Decision Flowchart
Start
│
├─► Is this a simple A→B transfer?
│ │
│ ├─► Yes ──► Use /quote
│ │
│ └─► No ──► Use /advanced/routes
│
├─► Is the agent server-side?
│ │
│ ├─► Yes ──► Use API directly
│ │
│ └─► No ──► Consider SDK or Widget
│
├─► Is fromChain === toChain?
│ │
│ ├─► Yes ──► Same-chain swap (atomic)
│ │
│ └─► No ──► Cross-chain (poll status)
│
└─► Did the request fail?
│
├─► 429 ──► Retry with backoff
├─► 4xx ──► Fix parameters
└─► 5xx ──► Retry once