1inch API Authentication: Complete Developer Guide
Learn how to authenticate with the 1inch API, set up API keys, handle errors, and build real trading integrations with working Python and JavaScript examples.
Learn how to authenticate with the 1inch API, set up API keys, handle errors, and build real trading integrations with working Python and JavaScript examples.
The 1inch API is one of the most powerful tools in a DeFi trader's arsenal. It aggregates liquidity from dozens of decentralized exchanges — Uniswap, Curve, Balancer, and more — and finds the best swap route automatically. But before you can tap into that power programmatically, you need to authenticate properly. Mess it up and you get 401 errors all day. Get it right and you unlock real-time quote fetching, swap execution, and portfolio-level routing logic that can run 24/7 without you touching a keyboard.
1inch uses API key authentication via the Authorization HTTP header. The key is passed as a Bearer token with every request. There's no OAuth flow, no session cookies, no HMAC signing like you'd see on centralized exchanges like Binance or Bybit — it's straightforward Bearer token auth, which makes it easy to integrate into any stack.
The 1inch Developer Portal (portal.1inch.dev) is where you register and manage your API keys. As of 2024, the Fusion+ and Swap APIs require an active key — unauthenticated requests to the v6 endpoints return 401. Free tier keys exist, but rate limits are tight. For production bots or algo trading setups, you'll want to look at their paid tiers.
Important: Never expose your API key in frontend code or public repositories. Treat it like a private key — if it leaks, revoke it immediately from the developer portal.
Below is a complete Python setup that fetches a swap quote from 1inch for ETH → USDC on Ethereum mainnet (chain ID 1). This covers authentication, request construction, response parsing, and basic error handling.
import requests
import os
from typing import Optional
API_KEY = os.environ.get("INCH_API_KEY") # load from env, never hardcode
BASE_URL = "https://api.1inch.dev/swap/v6.0"
CHAIN_ID = 1 # Ethereum mainnet
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Accept": "application/json",
}
def get_quote(
src: str,
dst: str,
amount: str,
chain_id: int = CHAIN_ID,
) -> Optional[dict]:
"""
Fetch swap quote from 1inch API.
src/dst: token contract addresses
amount: amount in smallest unit (wei for ETH)
"""
url = f"{BASE_URL}/{chain_id}/quote"
params = {
"src": src,
"dst": dst,
"amount": amount,
}
try:
response = requests.get(url, headers=HEADERS, params=params, timeout=10)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if response.status_code == 401:
print("Authentication failed — check your API key")
elif response.status_code == 429:
print("Rate limit hit — back off and retry")
else:
print(f"HTTP error {response.status_code}: {e}")
return None
except requests.exceptions.Timeout:
print("Request timed out")
return None
# ETH → USDC, 0.1 ETH
ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
AMOUNT = str(int(0.1 * 10**18)) # 0.1 ETH in wei
quote = get_quote(ETH, USDC, AMOUNT)
if quote:
dst_amount = int(quote["dstAmount"]) / 10**6 # USDC has 6 decimals
print(f"You get: {dst_amount:.2f} USDC")
print(f"Gas estimate: {quote.get('gas', 'N/A')}")
print(f"Route protocols: {[p[0]['name'] for p in quote.get('protocols', [[{'name': 'N/A'}]])][:3]}")
If you're building a Node.js bot or a backend service, here's the JavaScript equivalent. This example shows how to fetch a quote and build a swap transaction object ready for signing. Traders who run bots across Binance for CEX fills and 1inch for DEX fills often use this pattern to route orders dynamically.
const API_KEY = process.env.INCH_API_KEY;
const BASE_URL = 'https://api.1inch.dev/swap/v6.0';
const CHAIN_ID = 1; // Ethereum mainnet
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Accept': 'application/json',
};
async function getSwapTransaction(src, dst, amount, fromAddress, slippage = 1) {
const url = `${BASE_URL}/${CHAIN_ID}/swap`;
const params = new URLSearchParams({
src,
dst,
amount,
from: fromAddress,
slippage: slippage.toString(),
disableEstimate: 'false',
});
const response = await fetch(`${url}?${params}`, { headers });
if (!response.ok) {
const errorBody = await response.json().catch(() => ({}));
if (response.status === 401) {
throw new Error('1inch API: invalid or missing API key');
}
if (response.status === 400) {
throw new Error(`1inch API bad request: ${errorBody.description || 'unknown'}`);
}
throw new Error(`1inch API error ${response.status}`);
}
const data = await response.json();
return {
to: data.tx.to,
data: data.tx.data,
value: data.tx.value,
gas: data.tx.gas,
dstAmount: data.dstAmount,
};
}
// Example usage
const ETH = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
const WALLET = '0xYourWalletAddress';
const AMOUNT = (0.1 * 1e18).toString(); // 0.1 ETH
getSwapTransaction(ETH, USDC, AMOUNT, WALLET)
.then(tx => {
console.log('Swap tx ready:', tx);
console.log(`Estimated output: ${parseInt(tx.dstAmount) / 1e6} USDC`);
// Sign and send tx with ethers.js or web3.js
})
.catch(err => console.error('Swap failed:', err.message));
Rate limiting is the biggest operational headache with the 1inch API on free and entry-level tiers. The API returns 429 when you exceed your quota. A proper retry strategy with exponential backoff is non-negotiable for any production bot. Here's a reusable Python decorator that handles this:
import time
import functools
import requests
def with_retry(max_retries=3, backoff_factor=2):
"""Retry decorator for 1inch API calls with exponential backoff."""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
delay = 1
for attempt in range(max_retries):
try:
result = func(*args, **kwargs)
if result is not None:
return result
except requests.exceptions.HTTPError as e:
status = e.response.status_code if e.response else 0
if status == 429:
print(f"Rate limited. Waiting {delay}s before retry {attempt + 1}/{max_retries}")
time.sleep(delay)
delay *= backoff_factor
continue
elif status in (500, 502, 503):
print(f"Server error {status}. Retrying...")
time.sleep(delay)
delay *= backoff_factor
continue
raise # re-raise non-retriable errors
print("Max retries exceeded")
return None
return wrapper
return decorator
@with_retry(max_retries=3, backoff_factor=2)
def get_quote_with_retry(src, dst, amount):
return get_quote(src, dst, amount) # your existing function
Tip: If you're running signals or execution logic based on real-time DeFi prices, pair your 1inch integration with a platform like VoiceOfChain to get pre-processed on-chain signals. This lets you trigger 1inch swaps only when signal conditions are met, reducing unnecessary API calls and improving your rate limit budget.
1inch supports multiple EVM chains — the same API key works across all of them, you just change the chain ID in the URL. This is hugely useful if you're routing trades across Ethereum, Polygon, BNB Chain, Arbitrum, or Optimism depending on gas costs and liquidity depth. Traders who also use OKX's DEX or Bybit's Web3 wallet for multi-chain exposure often use the same authenticated 1inch client across all networks.
| Network | Chain ID | Native Token |
|---|---|---|
| Ethereum | 1 | ETH |
| BNB Chain | 56 | BNB |
| Polygon | 137 | MATIC |
| Arbitrum One | 42161 | ETH |
| Optimism | 10 | ETH |
| Avalanche | 43114 | AVAX |
| Base | 8453 | ETH |
| Gnosis | 100 | xDAI |
Switching chains is as simple as changing the path segment. If you're fetching a quote on BNB Chain instead of Ethereum, replace `/v6.0/1/quote` with `/v6.0/56/quote`. The authentication header stays the same. This makes building multi-chain bots much cleaner — one authenticated client, multiple networks.
The 1inch API's authentication model is deliberately simple — Bearer tokens, REST endpoints, JSON responses. The complexity is in what you do with it: multi-chain routing, slippage management, MEV protection via Fusion+, and integrating DEX execution alongside CEX positions on platforms like Binance, Bybit, or Coinbase. Once your authentication is solid and error handling is in place, you've got a reliable foundation for everything from price comparison scripts to fully automated DeFi trading bots. Start with the Quote endpoint to get comfortable, then move to Swap once you're ready to execute on-chain.
If you want to add signal intelligence on top of raw execution, VoiceOfChain provides real-time on-chain flow data that pairs well with 1inch execution — trigger swaps only when whale accumulation or imbalance signals align with your thesis, rather than polling the API blindly on a timer.