Getting Started
swapapi is a free token swap API that returns executable calldata. No API key, no account, no SDK — just a GET request and you get back a transaction ready to submit on-chain.
Base URL: https://api.swapapi.dev
Your first request
Swap 1 ETH for USDC on Ethereum mainnet:
curl "https://api.swapapi.dev/v1/swap/1?\
tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&\
tokenOut=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&\
amount=1000000000000000000&\
sender=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
That's it. There is no step 2.
The response
{
"success": true,
"data": {
"status": "Successful",
"tokenFrom": {
"address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
"symbol": "ETH",
"name": "Ether",
"decimals": 18
},
"tokenTo": {
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"symbol": "USDC",
"name": "USD Coin",
"decimals": 6
},
"swapPrice": 2435.12,
"priceImpact": 0.0003,
"amountIn": "1000000000000000000",
"expectedAmountOut": "2435120000",
"tx": {
"from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"to": "0x011E52E4E40CF9498c79e329EBc29ed08c8B5abB",
"data": "0x2646478b...",
"value": "1000000000000000000",
"gasPrice": 30000000000,
"gas": "250000"
}
},
"timestamp": "2026-03-12T00:00:00.000Z"
}
Field reference
| Field | Type | Description |
|---|---|---|
success | boolean | true if the request succeeded |
data.status | string | "Successful", "Partial", or "NoRoute" |
data.tokenFrom | object | Input token metadata (address, symbol, name, decimals) |
data.tokenTo | object | Output token metadata (address, symbol, name, decimals) |
data.swapPrice | number | Exchange rate (output per input token) |
data.priceImpact | number | Price impact as a decimal (0.001 = 0.1%) |
data.amountIn | string | Input amount in wei (same as your request) |
data.expectedAmountOut | string | Guaranteed minimum output amount in token's smallest unit |
data.tx.from | string | Your sender address |
data.tx.to | string | Router contract address |
data.tx.data | string | Encoded calldata — submit this on-chain |
data.tx.value | string | Native token value to send (non-zero for native ETH swaps) |
data.tx.gasPrice | number | Suggested gas price in wei |
data.tx.gas | string | Estimated gas limit |
timestamp | string | ISO 8601 response timestamp |
Submit the swap (curl + JSON-RPC)
You can go from quote to on-chain execution with nothing but curl. No libraries, no SDKs.
1. Get the quote
curl -s "https://api.swapapi.dev/v1/swap/8453?\
tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&\
tokenOut=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&\
amount=1000000000000000000&\
sender=0xYOUR_ADDRESS" | jq .
2. Sign the transaction locally
You need to sign the tx object from the response. Use cast (from Foundry):
# Using the tx fields from the response:
cast send \
--rpc-url https://mainnet.base.org \
--private-key 0xYOUR_PRIVATE_KEY \
0x011E52E4E40CF9498c79e329EBc29ed08c8B5abB \
--value 1000000000000000000 \
--gas-limit 250000 \
--data 0x2646478b...
3. Or use raw JSON-RPC
If you don't have cast, you can sign with any tool and broadcast the raw signed transaction via RPC:
# eth_sendRawTransaction — broadcast a signed transaction
curl -X POST https://mainnet.base.org \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": ["0xSIGNED_TX_HEX"],
"id": 1
}'
{
"jsonrpc": "2.0",
"id": 1,
"result": "0xtransaction_hash..."
}
4. Check the result
# eth_getTransactionReceipt — check if it confirmed
curl -X POST https://mainnet.base.org \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": ["0xYOUR_TX_HASH"],
"id": 1
}'
The API gives you unsigned transaction data. You must sign it with the sender's private key before broadcasting. This is the one step that requires a tool — cast, a wallet library, or any ECDSA signer. The API never touches your private key.
Full script (bash + cast)
A complete swap in one script, zero dependencies beyond curl and cast:
#!/bin/bash
set -e
RPC_URL="https://mainnet.base.org"
SENDER="0xYOUR_ADDRESS"
PRIVATE_KEY="0xYOUR_PRIVATE_KEY"
# 1. Get swap quote
RESPONSE=$(curl -s "https://api.swapapi.dev/v1/swap/8453?\
tokenIn=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&\
tokenOut=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&\
amount=1000000000000000000&\
sender=$SENDER")
# 2. Parse the tx fields
TX_TO=$(echo "$RESPONSE" | jq -r '.data.tx.to')
TX_DATA=$(echo "$RESPONSE" | jq -r '.data.tx.data')
TX_VALUE=$(echo "$RESPONSE" | jq -r '.data.tx.value')
TX_GAS=$(echo "$RESPONSE" | jq -r '.data.tx.gas')
EXPECTED_OUT=$(echo "$RESPONSE" | jq -r '.data.expectedAmountOut')
echo "Swapping 1 ETH for minimum $(echo "scale=2; $EXPECTED_OUT / 1000000" | bc) USDC"
# 3. Sign and send
cast send \
--rpc-url "$RPC_URL" \
--private-key "$PRIVATE_KEY" \
"$TX_TO" \
--value "$TX_VALUE" \
--gas-limit "$TX_GAS" \
--data "$TX_DATA"
Quick reference
Endpoint: GET https://api.swapapi.dev/v1/swap/{chainId}
Auth: None
Rate limit: 60 requests/minute per IP
Chains: Ethereum (1), Base (8453), Arbitrum (42161), Polygon (137), Optimism (10), and more
OpenAPI spec: api.swapapi.dev/openapi.json