Cross-Chain Swaps
Cross-chain swaps (bridging) let you move tokens between different blockchain networks through a single API call. Suwappu handles the routing, bridging protocol selection, and settlement automatically.
How It Works
To perform a cross-chain swap, include both from_chain and to_chain parameters in your POST /quote request. When these differ, Suwappu routes the transaction through the optimal bridge.
POST /quote
{
class="hl-str">"from_token": class="hl-str">"USDC",
class="hl-str">"to_token": class="hl-str">"USDC",
class="hl-str">"amount": class="hl-str">"1000",
class="hl-str">"from_chain": class="hl-str">"ethereum",
class="hl-str">"to_chain": class="hl-str">"arbitrum"
}
The quote response includes the expected output amount after bridge fees and slippage. Execute the quote the same way as a single-chain swap -- via POST /swap/execute.
Important Considerations
- Settlement time: Cross-chain swaps take longer than same-chain swaps. Ethereum to L2 bridges typically complete in 1-15 minutes. L2 to L1 withdrawals can take longer depending on the bridge used.
- Bridge fees: The quoted output amount accounts for bridge fees. The
expected_outputfield reflects what you will receive after all fees. - Status tracking: Use
GET /swap/status/{swapId}to poll for completion. Cross-chain swaps may stay in"pending"status longer than same-chain swaps. - Token availability: Not all token pairs are available for cross-chain swaps. The quote endpoint will return an error if no route is found.
Full Example: Bridge USDC from Ethereum to Arbitrum
Step 1: Get a Cross-Chain Quote
-kw">curl -X POST https://api.suwappu.bot/v1/agent/quote \
-H -str">"Authorization: Bearer suwappu_sk_your_api_key" \
-H -str">"Content-Type: application/json" \
-d -str">'{
-str">"from_token": -str">"USDC",
-str">"to_token": -str">"USDC",
-str">"amount": -str">"1000",
-str">"from_chain": -str">"ethereum",
-str">"to_chain": -str">"arbitrum"
}'
#### Example Response
{
"hl-key">"success": true,
"hl-key">"quote_id": "qt_bridge_x1y2z3",
"hl-key">"from_token": "USDC",
"hl-key">"to_token": "USDC",
"hl-key">"amount": "1000",
"hl-key">"expected_output": "999.15",
"hl-key">"from_chain": "ethereum",
"hl-key">"to_chain": "arbitrum",
"hl-key">"expires_at": "2026-03-07T12:05:00Z"
}
Step 2: Execute the Swap
-kw">curl -X POST https://api.suwappu.bot/v1/agent/swap/execute \
-H -str">"Authorization: Bearer suwappu_sk_your_api_key" \
-H -str">"Content-Type: application/json" \
-d -str">'{-str">"quote_id": -str">"qt_bridge_x1y2z3"}'
#### Example Response
{
"hl-key">"success": true,
"hl-key">"swap_id": 5201,
"hl-key">"status": "submitted",
"hl-key">"tx_hash": "0x7b2a...e91f"
}
Step 3: Check Status Until Complete
-kw">curl https://api.suwappu.bot/v1/agent/swap/status/5201 \
-H -str">"Authorization: Bearer suwappu_sk_your_api_key"
#### Example Response (in progress)
{
"hl-key">"success": true,
"hl-key">"swap_id": 5201,
"hl-key">"status": "pending",
"hl-key">"tx_hash": "0x7b2a...e91f",
"hl-key">"from_token": "USDC",
"hl-key">"to_token": "USDC"
}
#### Example Response (completed)
{
"hl-key">"success": true,
"hl-key">"swap_id": 5201,
"hl-key">"status": "completed",
"hl-key">"tx_hash": "0x7b2a...e91f",
"hl-key">"from_token": "USDC",
"hl-key">"to_token": "USDC"
}
Python Example
import requests
import time
API_KEY = class="hl-str">"suwappu_sk_your_api_key"
BASE_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//api.suwappu.bot/v1/agent"
headers = {class="hl-str">"Authorization": fclass="hl-str">"Bearer {API_KEY}"}
class=class="hl-str">"hl-comment"># Step 1: Get a cross-chain quote
quote_response = requests.post(
fclass="hl-str">"{BASE_URL}/quote",
headers=headers,
json={
class="hl-str">"from_token": class="hl-str">"USDC",
class="hl-str">"to_token": class="hl-str">"USDC",
class="hl-str">"amount": class="hl-str">"1000",
class="hl-str">"from_chain": class="hl-str">"ethereum",
class="hl-str">"to_chain": class="hl-str">"arbitrum",
},
)
quote = quote_response.json()
print(fclass="hl-str">"Expected output: {quote[class="hl-str">'expected_output']} USDC on Arbitrum")
class=class="hl-str">"hl-comment"># Step 2: Execute the swap
swap_response = requests.post(
fclass="hl-str">"{BASE_URL}/swap/execute",
headers=headers,
json={class="hl-str">"quote_id": quote[class="hl-str">"quote_id"]},
)
swap = swap_response.json()
swap_id = swap[class="hl-str">"swap_id"]
print(fclass="hl-str">"Swap submitted: {swap_id}")
class=class="hl-str">"hl-comment"># Step 3: Poll for completion
while True:
status_response = requests.get(
fclass="hl-str">"{BASE_URL}/swap/status/{swap_id}",
headers=headers,
)
status = status_response.json()
print(fclass="hl-str">"Status: {status[class="hl-str">'status']}")
if status[class="hl-str">"status"] in (class="hl-str">"completed", class="hl-str">"failed"):
break
time.sleep(10) class=class="hl-str">"hl-comment"># Cross-chain swaps can take minutes
if status[class="hl-str">"status"] == class="hl-str">"completed":
print(fclass="hl-str">"Bridge complete! TX: {status[class="hl-str">'tx_hash']}")
else:
print(class="hl-str">"Bridge failed.")
TypeScript Example
const API_KEY = class="hl-str">"suwappu_sk_your_api_key";
const BASE_URL = class="hl-str">"https:class="hl-commentclass="hl-str">">//api.suwappu.bot/v1/agent";
const headers = {
Authorization: Bearer ${API_KEY},
class="hl-str">"Content-Type": class="hl-str">"application/json",
};
class=class="hl-str">"hl-comment">// Step 1: Get a cross-chain quote
const quoteRes = await fetch(${BASE_URL}/quote, {
method: class="hl-str">"POST",
headers,
body: JSON.stringify({
from_token: class="hl-str">"USDC",
to_token: class="hl-str">"USDC",
amount: class="hl-str">"1000",
from_chain: class="hl-str">"ethereum",
to_chain: class="hl-str">"arbitrum",
}),
});
const quote = await quoteRes.json();
console.log(Expected output: ${quote.expected_output} USDC on Arbitrum);
class=class="hl-str">"hl-comment">// Step 2: Execute the swap
const swapRes = await fetch(${BASE_URL}/swap/execute, {
method: class="hl-str">"POST",
headers,
body: JSON.stringify({ quote_id: quote.quote_id }),
});
const swap = await swapRes.json();
const swapId = swap.swap_id;
console.log(Swap submitted: ${swapId});
class=class="hl-str">"hl-comment">// Step 3: Poll for completion
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
while (true) {
const statusRes = await fetch(${BASE_URL}/swap/status/${swapId}, {
headers: { Authorization: Bearer ${API_KEY} },
});
const status = await statusRes.json();
console.log(Status: ${status.status});
if (status.status === class="hl-str">"completed" || status.status === class="hl-str">"failed") {
if (status.status === class="hl-str">"completed") {
console.log(Bridge complete! TX: ${status.tx_hash});
} else {
console.log(class="hl-str">"Bridge failed.");
}
break;
}
await sleep(10_000); class=class="hl-str">"hl-comment">// Cross-chain swaps can take minutes
}
Supported Cross-Chain Routes
Cross-chain swaps are supported between all EVM chains. The most common routes include:
- Ethereum to/from L2s (Arbitrum, Optimism, Base)
- Between L2s (e.g., Arbitrum to Base)
- Stablecoin bridges (USDC, USDT) across any EVM pair
Use the POST /quote endpoint to check if a specific route is available. If no bridge route exists, the API returns an error with a descriptive message.