Documentation Index
Fetch the complete documentation index at: https://docs.li.fi/llms.txt
Use this file to discover all available pages before exploring further.
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=stargateV2,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