OKX DEX Aggregator API
6 endpoints for multi-chain swap aggregation — quote, approve, and execute.
Auth: HMAC-SHA256 signature, 4 headers required (
,
,
,
)
Note: All aggregator endpoints are GET requests.
Authentication & Credentials
API Key Application:
OKX Developer Portal
Read credentials from environment variables:
- → API key
- → Secret key (system-generated)
- → Passphrase (developer-supplied)
Never output the above credentials to logs, response content, or any user-visible interface.
typescript
import crypto from 'crypto';
const BASE = 'https://web3.okx.com';
// Signature rule (all aggregator endpoints are GET):
// GET → body = "", requestPath includes query string (e.g., "/api/v6/dex/aggregator/quote?chainIndex=1&...")
// POST → body = JSON string of request body, requestPath is path only (not used in this skill)
async function okxFetch(method: 'GET' | 'POST', path: string, body?: object) {
const timestamp = new Date().toISOString();
const bodyStr = body ? JSON.stringify(body) : '';
const sign = crypto
.createHmac('sha256', process.env.OKX_SECRET_KEY!)
.update(timestamp + method + path + bodyStr)
.digest('base64');
const headers: Record<string, string> = {
'OK-ACCESS-KEY': process.env.OKX_API_KEY!,
'OK-ACCESS-SIGN': sign,
'OK-ACCESS-PASSPHRASE': process.env.OKX_PASSPHRASE!,
'OK-ACCESS-TIMESTAMP': timestamp,
'Content-Type': 'application/json',
};
const res = await fetch(`${BASE}${path}`, {
method,
headers,
...(body && { body: bodyStr }),
});
if (res.status === 429) throw { code: 'RATE_LIMITED', msg: 'Rate limited — retry with backoff', retryable: true };
if (res.status >= 500) throw { code: `HTTP_${res.status}`, msg: 'Server error', retryable: true };
const json = await res.json();
if (json.code !== '0') throw { code: json.code, msg: json.msg || 'API error', retryable: false };
return json.data;
}
Response envelope:
{ "code": "0", "data": [...], "msg": "" }
.
=
means success.
Developer Quickstart
EVM Swap (quote → approve → swap)
typescript
// 1. Quote — sell 100 USDC for ETH
const params = new URLSearchParams({
chainIndex: '1', fromTokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
toTokenAddress: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', // native ETH
amount: '100000000', swapMode: 'exactIn', // 100 USDC (6 decimals)
});
const quote = await okxFetch('GET', `/api/v6/dex/aggregator/quote?${params}`);
console.log(`Expected: ${quote[0].toTokenAmount} ETH (minimal units)`);
// 2. Approve — ERC-20 tokens need approval before swap (skip for native ETH)
const approveParams = new URLSearchParams({
chainIndex: '1', tokenContractAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
approveAmount: '100000000',
});
const approve = await okxFetch('GET', `/api/v6/dex/aggregator/approve-transaction?${approveParams}`);
// → build tx: { to: tokenContractAddress, data: approve[0].data }, sign & send
// approve[0].dexContractAddress is the spender (already encoded in calldata), NOT the tx target
// 3. Swap
const swapParams = new URLSearchParams({
chainIndex: '1', fromTokenAddress: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
toTokenAddress: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
amount: '100000000', slippagePercent: '1',
userWalletAddress: '0xYourWallet', swapMode: 'exactIn',
});
const swap = await okxFetch('GET', `/api/v6/dex/aggregator/swap?${swapParams}`);
// → sign & send swap[0].tx { from, to, data, value, gas }
Solana Swap (swap-instruction)
typescript
const params = new URLSearchParams({
chainIndex: '501', fromTokenAddress: '11111111111111111111111111111111', // native SOL
toTokenAddress: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', // BONK
amount: '1000000000', slippagePercent: '1', userWalletAddress: 'YourSolanaWallet',
});
const result = await okxFetch('GET', `/api/v6/dex/aggregator/swap-instruction?${params}`);
// → result[0].instructionLists: assemble into VersionedTransaction, sign & send
Common Chain IDs
| Chain | chainIndex | Chain | chainIndex |
|---|
| Ethereum | | Arbitrum | |
| BSC | | Base | |
| Polygon | | Solana | |
Native Token Addresses
CRITICAL: Each chain has a specific native token address for use in OKX DEX API. Using the wrong address (e.g., wSOL SPL token address instead of the Solana system program address) will cause swap transactions to fail. Reference:
DEX Aggregation FAQ
| Chain | Native Token Address |
|---|
| EVM (Ethereum, BSC, Polygon, Arbitrum, Base, etc.) | 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
| Solana | 11111111111111111111111111111111
|
| Sui | |
| Tron | T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb
|
| Ton | EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c
|
WARNING — Solana native SOL: The correct address is
11111111111111111111111111111111
(Solana system program). Do
NOT use
So11111111111111111111111111111111111111112
(wSOL SPL token) — it is a different token and will cause swap failures (
custom program error: 0xb
).
Endpoint Index
Cross-Skill Workflows
This skill is the execution endpoint of most user trading flows. It almost always needs input from other skills first.
Workflow A: Full Swap by Token Name (most common)
User: "Swap 1 SOL for BONK on Solana"
1. okx-dex-token /market/token/search?search=BONK&chains=501 → get BONK tokenContractAddress
↓ tokenContractAddress
2. okx-wallet-portfolio /balance/all-token-balances-by-address → verify SOL balance >= 1
↓ sufficient balance confirmed
3. okx-dex-swap /aggregator/quote → get quote (show expected output, gas, price impact)
↓ user confirms
4. okx-dex-swap /aggregator/swap-instruction → get serialized instruction (Solana)
5. User signs & sends tx (or use `okx-onchain-gateway` to broadcast via OKX nodes)
Data handoff:
- from step 1 → in steps 3-4
- SOL native address =
"11111111111111111111111111111111"
(Solana system program) → . Do NOT use So11111111111111111111111111111111111111112
(wSOL) — see Native Token Addresses.
- Amount = (9 decimals) → param
- from step 2 is UI units; swap needs minimal units → multiply by
Workflow B: EVM Swap with Approval
User: "Swap 100 USDC for ETH on Ethereum"
1. okx-dex-token /market/token/search?search=USDC&chains=1 → get USDC address
2. okx-wallet-portfolio /balance/token-balances-by-address → verify USDC balance >= 100
3. okx-dex-swap /aggregator/quote → get quote
↓ check isHoneyPot, taxRate, priceImpactPercent
4. okx-dex-swap /aggregator/approve-transaction → get ERC-20 approval calldata
5. User signs & sends approval tx
6. okx-dex-swap /aggregator/swap → get swap calldata
7. User signs & sends swap tx (or use `okx-onchain-gateway` to broadcast via OKX nodes)
Key: EVM tokens (not native ETH) require an approve step. Skip it if user is selling native ETH.
Workflow C: Compare Quote Then Execute
1. okx-dex-swap /aggregator/quote → get quote with route info
2. Display to user: expected output, gas, price impact, route
3. If price impact > 5% → warn user
4. If isHoneyPot = true → block trade, warn user
5. User confirms → proceed to approve (if EVM) → swap
Swap Flow
EVM Chains (Ethereum, BSC, Arbitrum, Base, etc.)
1. GET /aggregator/quote -> Get price and route
2. GET /aggregator/approve-transaction -> Get approval calldata (if needed)
3. User signs & sends approval tx
4. GET /aggregator/swap -> Get swap calldata
5. User signs & sends swap tx
Solana
1. GET /aggregator/quote -> Get price and route
2. GET /aggregator/swap-instruction -> Get serialized instruction
3. User signs & sends tx
Operation Flow
Step 1: Identify Intent
- View a quote ->
- Execute a swap -> full swap flow (quote -> approve -> swap)
- List available DEXes ->
GET /aggregator/get-liquidity
- Approve a token ->
GET /aggregator/approve-transaction
Step 2: Collect Parameters
- Missing -> ask which chain
- Missing token addresses -> use to resolve name → address
- Missing amount -> ask user, remind to convert to minimal units
- Missing slippage -> suggest 1% default, 3-5% for volatile tokens
- Missing wallet address -> ask user
Step 3: Execute
- Quote phase: call , display estimated results
- Expected output, gas estimate, price impact, routing path
- Check and — surface safety info to users
- Confirmation phase: wait for user approval before proceeding
- Approval phase (EVM only): check/execute approve if selling non-native token
- Execution phase: call (EVM) or (Solana), return tx data for signing
Step 4: Suggest Next Steps
After displaying results, suggest 2-3 relevant follow-up actions based on the swap phase just completed:
| Just completed | Suggest |
|---|
| (quote only, not yet confirmed) | 1. Check wallet balance first → 2. View price chart before deciding → 3. Proceed with swap → continue approve + swap (this skill) |
| Swap executed successfully | 1. Verify updated balance → 2. Check price of the token just received → 3. Swap another token → new swap flow (this skill) |
/aggregator/get-liquidity
| 1. Get a swap quote → (this skill) |
Present conversationally, e.g.: "Swap complete! Would you like to check your updated balance?" — never expose skill names or endpoint paths to the user.
API Reference
1. GET /aggregator/supported/chain
| Param | Type | Required | Description |
|---|
| String | No | Filter to a specific chain (e.g., ) |
Response:
| Field | Type | Description |
|---|
| String | Chain unique identifier (e.g., "1") |
| String | Chain name (e.g., "Ethereum") |
data[].dexTokenApproveAddress
| String | OKX DEX token approve contract address |
2. GET /aggregator/get-liquidity
| Param | Type | Required | Description |
|---|
| String | Yes | Chain ID |
Response:
| Field | Type | Description |
|---|
| String | Liquidity pool ID |
| String | Pool name (e.g., "Uniswap V3") |
| String | Pool logo URL |
3. GET /aggregator/approve-transaction
| Param | Type | Required | Description |
|---|
| String | Yes | Chain ID |
| String | Yes | Token to approve |
| String | Yes | Amount in minimal units |
Response:
| Field | Type | Description |
|---|
| String | Approval calldata (approve(dexContractAddress, amount)
) |
data[].dexContractAddress
| String | DEX router address (the spender, already encoded in calldata). NOT the tx — send tx to the token contract |
| String | Gas limit. May underestimate — use simulation or ×1.5 |
| String | Gas price in wei |
4. GET /aggregator/quote
| Param | Type | Required | Description |
|---|
| String | Yes | Chain ID |
| String | Yes | Amount in minimal units (sell amount if exactIn, buy amount if exactOut) |
| String | Yes | (default) or |
| String | Yes | Token to sell |
| String | Yes | Token to buy |
Optional params:
,
,
priceImpactProtectionPercent
(default 90%),
(max 10 Solana, 3 others).
Response key fields:
(output minimal units),
,
,
(USD estimate),
,
,
,
/
(each has
,
,
,
). Full fields: see
docs.
5. GET /aggregator/swap-instruction (Solana only)
| Param | Type | Required | Description |
|---|
| String | Yes | Must be (Solana) |
| String | Yes | Amount in minimal units |
| String | Yes | Token to sell |
| String | Yes | Token to buy |
| String | Yes | User's wallet |
| String | Yes | 0 to <100 |
Optional params:
,
,
,
,
,
,
priceImpactProtectionPercent
.
Response key fields:
(each has
,
,
),
addressLookupTableAccount
,
(same as /quote),
(
,
),
. Full fields: see
docs.
6. GET /aggregator/swap (EVM + Solana)
Note: This endpoint works for
all chains including Solana.
is a Solana-specific alternative that returns deserialized instructions instead of a serialized transaction.
| Param | Type | Required | Description |
|---|
| String | No | Chain ID. Technically optional but strongly recommended — always pass it. |
| String | Yes | Amount in minimal units |
| String | Yes | (default) or |
| String | Yes | Token to sell |
| String | Yes | Token to buy |
| String | Yes | 0-100 (EVM), 0-<100 (Solana) |
| String | Yes | User's wallet |
Optional params:
(
/
/
),
,
,
(Jito, 0.0000000001-2 SOL; use
if
is set),
,
,
,
,
,
priceImpactProtectionPercent
(default 90%),
(Boolean, combine approve+swap in one call),
(used with
).
Response key fields:
(same as /quote),
—
,
,
(hex-encoded for EVM, base58-encoded for Solana),
,
,
(EIP-1559),
,
,
,
,
. Full fields: see
docs.
Input / Output Examples
User says: "Swap 100 USDC for ETH"
1. GET /api/v6/dex/aggregator/quote?chainIndex=1&fromTokenAddress=0xa0b8...&toTokenAddress=0xeeee...&amount=100000000&swapMode=exactIn
-> Display:
Expected output: 0.031 ETH
Gas fee: ~$2.50
Price impact: 0.05%
Route: USDC -> WETH -> ETH (Uniswap V3)
2. User confirms
3. GET /api/v6/dex/aggregator/approve-transaction?chainIndex=1&tokenContractAddress=0xa0b8...&approveAmount=100000000
-> Returns approval calldata and spender address
-> Build tx: { to: "0xa0b8..." (token contract), data: response.data } — sign & send
4. GET /api/v6/dex/aggregator/swap?chainIndex=1&...&slippagePercent=1&userWalletAddress=0x...
-> Returns tx: { from, to, data, gas, gasPrice, value, minReceiveAmount }
-> User signs and broadcasts
User says: "What DEXes are available on Ethereum?"
GET /api/v6/dex/aggregator/get-liquidity?chainIndex=1
-> Display: Uniswap V2, Uniswap V3, SushiSwap, Curve, Balancer, ... (80+ sources)
Edge Cases
- High slippage (>5%): warn user, suggest splitting the trade or adjusting slippage
- Large price impact (>10%): strongly warn, suggest reducing amount
- Honeypot token: — block trade and warn user
- Tax token: non-zero — display to user (e.g. 5% buy tax)
- Insufficient balance: use to check first, show current balance, suggest adjusting amount
- exactOut not supported: only Ethereum/Base/BSC/Arbitrum — prompt user to use
- Solana chain: returns deserialized instructions (more control); also works but returns a serialized transaction
- Solana native SOL address: Must use
11111111111111111111111111111111
(system program), NOT So11111111111111111111111111111111111111112
(wSOL). Using wSOL address causes custom program error: 0xb
on-chain failures. See DEX Aggregation FAQ.
- 429 rate limit: exponential backoff with jitter. See Rate Limit & Fee Docs for tier-specific RPS limits (Trial: 1 RPS, Start-up: 2-50 RPS, Enterprise: custom).
- Cross-skill pipeline rate limit: when chaining calls across multiple skills (e.g., token search → balance check → swap), add 300-500ms delay between requests to avoid triggering rate limit (error code ).
- Network error: retry once, then prompt user to try again later
- Request timeout: all API calls must set a 10-second timeout limit
Amount Display Rules
- Input/output amounts in UI units (, )
- Internal API params use minimal units ( = , = )
- Gas fees in USD
- in both UI units and USD
- Price impact as percentage
Global Notes
- All endpoints are GET — no POST in the aggregator family
- Amounts must be in minimal units (wei/lamports)
- only on Ethereum()/Base()/BSC()/Arbitrum()
- is Solana-only
- Check and — surface safety info to users
- Solana referrer wallets require SOL deposit activation
- TON chain has limited commission pool support (excludes Stonfi V1)
- EVM contract addresses must be all lowercase
- For token search -> use
- For market prices -> use
- For balance queries -> use
- For transaction broadcasting -> use