For Agent Frameworks
swapapi is a plain HTTP API. Any agent framework that can make HTTP requests can use it. Here are ready-made tool definitions for popular frameworks.
Base URL: https://api.swapapi.dev
LangChain Tool
from langchain_core.tools import tool
import requests
@tool
def swap_tokens(
chain_id: int,
token_in: str,
token_out: str,
amount: str,
sender: str,
max_slippage: float = 0.005,
) -> dict:
"""Get executable calldata for a token swap on an EVM chain.
Args:
chain_id: EVM chain ID (1=Ethereum, 8453=Base, 42161=Arbitrum)
token_in: Address of token to sell (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native ETH)
token_out: Address of token to buy
amount: Amount in wei (smallest token unit). 1 ETH = 1000000000000000000
sender: Wallet address that will execute the swap
max_slippage: Max slippage as decimal (0.005 = 0.5%)
Returns:
Swap quote with transaction data (to, data, value, gas) ready for on-chain execution.
"""
response = requests.get(
f"https://api.swapapi.dev/v1/swap/{chain_id}",
params={
"tokenIn": token_in,
"tokenOut": token_out,
"amount": amount,
"sender": sender,
"maxSlippage": max_slippage,
},
)
return response.json()
OpenAI Function Calling
{
"type": "function",
"function": {
"name": "get_swap_calldata",
"description": "Get executable transaction data for a token swap on an EVM chain. Returns calldata that can be submitted directly on-chain. No API key required.",
"parameters": {
"type": "object",
"required": ["chain_id", "token_in", "token_out", "amount", "sender"],
"properties": {
"chain_id": {
"type": "integer",
"description": "EVM chain ID. 1=Ethereum, 8453=Base, 42161=Arbitrum, 137=Polygon, 10=Optimism"
},
"token_in": {
"type": "string",
"description": "Address of token to sell. Use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native ETH."
},
"token_out": {
"type": "string",
"description": "Address of token to buy."
},
"amount": {
"type": "string",
"description": "Amount in wei (smallest unit). 1 ETH = 1000000000000000000, 1 USDC = 1000000."
},
"sender": {
"type": "string",
"description": "Wallet address that will sign and submit the swap transaction."
},
"max_slippage": {
"type": "number",
"description": "Maximum slippage tolerance as a decimal. 0.005 = 0.5%. Default: 0.005."
}
}
}
}
}
Implementation:
import requests
import json
def handle_get_swap_calldata(args):
response = requests.get(
f"https://api.swapapi.dev/v1/swap/{args['chain_id']}",
params={
"tokenIn": args["token_in"],
"tokenOut": args["token_out"],
"amount": args["amount"],
"sender": args["sender"],
"maxSlippage": args.get("max_slippage", 0.005),
},
)
return json.dumps(response.json())
Claude MCP Server
A minimal MCP server that wraps the swap API:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "swapapi",
version: "1.0.0",
});
server.tool(
"swap_tokens",
"Get executable calldata for a token swap. Returns transaction data (to, data, value, gas) ready for on-chain submission.",
{
chainId: z.number().describe("EVM chain ID (1=Ethereum, 8453=Base, 42161=Arbitrum)"),
tokenIn: z.string().describe("Token to sell. 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native ETH"),
tokenOut: z.string().describe("Token to buy"),
amount: z.string().describe("Amount in wei. 1 ETH = 1000000000000000000"),
sender: z.string().describe("Wallet address executing the swap"),
maxSlippage: z.number().optional().describe("Max slippage as decimal (default 0.005 = 0.5%)"),
},
async ({ chainId, tokenIn, tokenOut, amount, sender, maxSlippage }) => {
const params = new URLSearchParams({
tokenIn,
tokenOut,
amount,
sender,
...(maxSlippage !== undefined && { maxSlippage: String(maxSlippage) }),
});
const res = await fetch(
`https://api.swapapi.dev/v1/swap/${chainId}?${params}`
);
const data = await res.json();
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
Add to Claude Desktop config (claude_desktop_config.json):
{
"mcpServers": {
"swapapi": {
"command": "npx",
"args": ["tsx", "path/to/server.ts"]
}
}
}
CrewAI Tool
from crewai.tools import tool
import requests
@tool("Token Swap")
def swap_tokens(
chain_id: int,
token_in: str,
token_out: str,
amount: str,
sender: str,
) -> str:
"""Get executable swap calldata for an EVM token swap.
No API key needed. Returns transaction data ready for on-chain execution.
chain_id: EVM chain ID (1=Ethereum, 8453=Base, 42161=Arbitrum)
token_in: Token address to sell (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native ETH)
token_out: Token address to buy
amount: Amount in wei (1 ETH = 1000000000000000000)
sender: Wallet address executing the swap
"""
response = requests.get(
f"https://api.swapapi.dev/v1/swap/{chain_id}",
params={
"tokenIn": token_in,
"tokenOut": token_out,
"amount": amount,
"sender": sender,
},
)
return response.text
Vercel AI SDK Tool
import { tool } from "ai";
import { z } from "zod";
export const swapTokensTool = tool({
description:
"Get executable calldata for a token swap on an EVM chain. No auth required.",
parameters: z.object({
chainId: z.number().describe("EVM chain ID (1, 8453, 42161, 137, 10)"),
tokenIn: z.string().describe("Token to sell (address)"),
tokenOut: z.string().describe("Token to buy (address)"),
amount: z.string().describe("Amount in wei"),
sender: z.string().describe("Wallet address"),
maxSlippage: z.number().optional().describe("Max slippage decimal"),
}),
execute: async ({ chainId, tokenIn, tokenOut, amount, sender, maxSlippage }) => {
const params = new URLSearchParams({
tokenIn,
tokenOut,
amount,
sender,
...(maxSlippage !== undefined && { maxSlippage: String(maxSlippage) }),
});
const res = await fetch(
`https://api.swapapi.dev/v1/swap/${chainId}?${params}`
);
return res.json();
},
});
Why this works with any framework
swapapi is just HTTP. If your framework can:
- Make a
GETrequest - Parse JSON
...then it can use this API. No SDK, no WebSocket, no streaming, no auth headers. The OpenAPI spec at /openapi.json can also be imported directly into frameworks that support OpenAPI tool generation.
Quick reference
Endpoint: GET https://api.swapapi.dev/v1/swap/{chainId}
Required: tokenIn, tokenOut, amount, sender
Auth: None
OpenAPI spec: api.swapapi.dev/openapi.json
LLM discovery: api.swapapi.dev/llms.txt