Across for Stablecoins
Move native USDC, USDT0, and USDH across chains with a single Swap API call.
Across moves native stablecoins across every supported chain through one Swap API call — no wrapped tokens. You request a route; Across picks the best settlement path automatically and returns a transaction to execute.
API key required for production. Get your API key and Integrator ID to authenticate your requests.
Sponsored Routes
Select stablecoin routes have zero bridge fees, subsidized by the protocol.
Currently sponsored:
- USDT / USDT0 → USDC-SPOT, USDC-PERPS on HyperCore from Ethereum, Arbitrum, Monad, Polygon, Unichain
Sponsored routes change over time. To check if a route is currently sponsored, inspect the fees object in the /swap/approval response.
Stablecoin Contract Addresses
Always verify addresses via the /swap/tokens endpoint. Token addresses can change as new deployments roll out.
| Chain | Address |
|---|---|
| Ethereum | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| Arbitrum | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 |
| Base | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Optimism | 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 |
| Polygon | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 |
Use /swap/tokens?chainId=<id> for the complete list across all supported chains.
| Chain | Address |
|---|---|
| Ethereum | 0xdAC17F958D2ee523a2206206994597C13D831ec7 |
| Arbitrum | 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9 |
| Optimism | 0x94b008aA00579c1307B0EF2c499aD98a8ce58e58 |
Use /swap/tokens?chainId=<id> for the complete list.
This is a subset of supported chains. Query /swap/tokens for the full matrix of stablecoins and chains.
Example: Large USDC Transfer
One /swap/approval call quotes the route and returns the transaction(s) to execute. The integration code is the same for every stablecoin route, regardless of size.
import { createWalletClient, createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
const walletClient = createWalletClient({ account, chain: mainnet, transport: http() });
const publicClient = createPublicClient({ chain: mainnet, transport: http() });
const params = new URLSearchParams({
tradeType: "minOutput",
originChainId: "1",
destinationChainId: "42161",
inputToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC on Ethereum
outputToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
amount: "1000000000", // 1,000 USDC (6 decimals)
depositor: account.address,
});
const quote = await fetch(
`https://app.across.to/api/swap/approval?${params}`,
{ headers: { Authorization: "Bearer YOUR_API_KEY" } },
).then((r) => r.json());
// Execute approvals (if any), then the swap
if (quote.approvalTxns?.length) {
for (const approvalTx of quote.approvalTxns) {
const hash = await walletClient.sendTransaction({ to: approvalTx.to, data: approvalTx.data });
await publicClient.waitForTransactionReceipt({ hash });
}
}
const hash = await walletClient.sendTransaction({
to: quote.swapTx.to,
data: quote.swapTx.data,
value: quote.swapTx.value ? BigInt(quote.swapTx.value) : 0n,
});
console.log("Transfer tx:", hash);See the GET /swap/approval API reference for every parameter and the full response shape.
The integration code is identical for every stablecoin route — call /swap/approval, execute any approvals, then send the returned transaction. Across handles settlement behind the scenes.