Multi-Token Payments
Multi-Token lets your customers pay with a token they already hold while your merchant account settles in the configured settlement token for that account. In Coal today, that is typically USDC unless a custom settlement token has been configured.
Powered by Li.Fi, Coal can quote and route a cross-chain swap or same-chain swap between the customer token and the configured settlement token.
Multi-Token is currently in beta. Enable it under Console → Settings → Multi-Token.
How It Works
- The customer selects an input token in the Coal checkout.
- Coal fetches a Li.Fi quote for the configured settlement amount.
- The customer reviews the quote, including estimated gas and slippage.
- The customer signs the swap transaction in their wallet.
- Li.Fi routes the swap across DEXes or bridges as needed.
- Your merchant wallet receives the configured settlement token.
Supported Input Tokens
| Token | Networks |
|---|---|
| ETH | Ethereum, Arbitrum, Optimism, Base |
| USDC | Ethereum, Arbitrum, Optimism, Base, Polygon |
| USDT | Ethereum, Arbitrum, Polygon, BNB Chain |
| MATIC | Polygon |
| BNB | BNB Chain |
| DAI | Ethereum, Arbitrum, Polygon |
| WBTC | Ethereum, Arbitrum |
| ARB | Arbitrum |
| OP | Optimism |
Support for additional tokens depends on Li.Fi liquidity routing. The checkout UI only shows tokens that can realistically route to the configured settlement token.
The Quotes API
GET /api/lifi/quote
1curl "https://api.usecoal.xyz/api/lifi/quote?fromToken=ETH&fromChain=ethereum&toAmount=49.99" \2 -H "x-api-key: coal_live_..."
Response:
1{2 "fromToken": "ETH",3 "fromChain": "ethereum",4 "fromAmount": "0.0281",5 "toToken": "USDC",6 "toAmount": "49.99",7 "slippage": 0.005,8 "estimatedGasUsd": "1.83",9 "estimatedDurationSeconds": 45,10 "route": {11 "steps": [12 {13 "type": "swap",14 "protocol": "Uniswap V3",15 "fromToken": "ETH",16 "toToken": "USDC"17 }18 ]19 },20 "expiresAt": "2026-03-22T12:01:30.000Z"21}
Quotes expire after 90 seconds. Re-fetch if the customer takes longer to confirm.
Using the Quote in Your Code
1export interface LifiQuote {2 fromToken: string;3 fromChain: string;4 fromAmount: string;5 toToken: string;6 toAmount: string;7 slippage: number;8 estimatedGasUsd: string;9 estimatedDurationSeconds: number;10 expiresAt: string;11}1213export async function getLifiQuote(14 fromToken: string,15 fromChain: string,16 toAmount: string17): Promise<LifiQuote> {18 const url = new URL('https://api.usecoal.xyz/api/lifi/quote');19 url.searchParams.set('fromToken', fromToken);20 url.searchParams.set('fromChain', fromChain);21 url.searchParams.set('toAmount', toAmount);2223 const res = await fetch(url.toString(), {24 headers: { 'x-api-key': process.env.COAL_API_KEY! },25 next: { revalidate: 0 },26 });2728 if (!res.ok) {29 throw new Error(`Li.Fi quote failed: ${res.status}`);30 }3132 return res.json();33}
1import { getLifiQuote } from '@/lib/lifi';23export default async function CheckoutPage() {4 const quote = await getLifiQuote('ETH', 'ethereum', '49.99');56 return (7 <div>8 <p>Pay with ETH: {quote.fromAmount} ETH</p>9 <p>Estimated gas: ${quote.estimatedGasUsd}</p>10 <p>You receive: {quote.toAmount} settlement-token units</p>11 </div>12 );13}
Slippage
Default slippage tolerance is 0.5% (0.005). This means Li.Fi may deliver up to 0.5% less than the quoted settlement amount. Coal's verification accounts for this tolerance, so a payment that lands within the slippage band is still marked confirmed.
To adjust slippage for a specific session:
1curl -X POST https://api.usecoal.xyz/api/checkouts \2 -H "Content-Type: application/json" \3 -H "x-api-key: coal_live_..." \4 -d '{5 "amount": 100.00,6 "description": "Annual Subscription",7 "multiToken": {8 "enabled": true,9 "slippage": 0.0110 }11 }'
Allowed range: 0.001 (0.1%) to 0.05 (5%).
Gas
Gas is paid by the customer in their source chain's native token (for example ETH for Ethereum swaps). The Li.Fi quote includes estimatedGasUsd so you can display the all-in cost before the customer signs.
Gas is never deducted from the settlement amount your merchant receives.
Enabling Multi-Token
- Open Console → Settings → Multi-Token.
- Toggle Enable Multi-Token Payments.
- Optionally set default slippage tolerance.
- Click Save.
Once enabled, the Coal checkout page automatically displays a token selector to customers.
To enable programmatically on a per-session basis:
1curl -X POST https://api.usecoal.xyz/api/checkouts \2 -H "Content-Type: application/json" \3 -H "x-api-key: coal_live_..." \4 -d '{5 "amount": 25.00,6 "description": "Pro Plan",7 "multiToken": {8 "enabled": true9 }10 }'
Webhook Payload
When a Multi-Token payment confirms, the webhook includes the original input token details alongside the settled amount:
1{2 "event": "checkout.confirmed",3 "id": "evt_clx7k2p3q0000abc12345",4 "timestamp": "2026-03-22T12:00:00.000Z",5 "data": {6 "sessionId": "clx7k2p3q0000abc12345",7 "merchantId": "clx1mer0h0000xyz98765",8 "amount": "49.99",9 "currency": "USDC",10 "status": "confirmed",11 "txHash": "0xabc123...",12 "multiToken": {13 "inputToken": "USDC",14 "inputChain": "arbitrum",15 "inputAmount": "50.24",16 "lifiTxHash": "0xdef456...",17 "route": "Uniswap V3"18 },19 "description": "Pro Plan",20 "metadata": {}21 }22}
Limitations
- Maximum single-payment value: 10,000 USD equivalent.
- Some token/chain combinations may return no quote if liquidity is insufficient. Fall back to the configured settlement-token flow in that case.
- Cross-chain swaps can take up to 3 minutes to settle. Sessions have a 35-minute expiry to accommodate this.
- Multi-Token is not compatible with
pricingModel: "per_call"paywalls.
