--- name: okx-dex-market description: "This skill should be used when the user asks 'what\\'s the price of OKB', 'check token price', 'how much is OKB', 'show me the price chart', 'get candlestick data', 'show K-line chart', 'view trade history', 'recent trades for SOL', 'price trend', 'index price', or mentions checking a token\\'s current price, viewing price charts, candlestick data, trade history, or historical price trends. Covers real-time on-chain prices, K-line/candlestick charts, trade logs, and index prices across XLayer, Solana, Ethereum, Base, BSC, Arbitrum, Polygon, and 20+ other chains. For token search, market cap, liquidity analysis, trending tokens, or holder distribution, use okx-dex-token instead." license: Apache-2.0 metadata: author: okx version: "1.0.0" homepage: "https://web3.okx.com" --- # OKX DEX Market Data API 7 endpoints for on-chain prices, trades, candlesticks, and index prices. **Base URL**: `https://web3.okx.com` **Base path**: `/api/v6/dex/market` and `/api/v6/dex/index` **Auth**: HMAC-SHA256 signature, 4 headers required (`OK-ACCESS-KEY`, `OK-ACCESS-SIGN`, `OK-ACCESS-PASSPHRASE`, `OK-ACCESS-TIMESTAMP`) ## Authentication & Credentials **API Key Application**: [OKX Developer Portal](https://web3.okx.com/onchain-os/dev-portal) **Setup Guide**: [Developer Portal Docs](https://web3.okx.com/onchain-os/dev-docs/wallet-api/developer-portal) Read credentials from environment variables: - `OKX_API_KEY` → API key - `OKX_SECRET_KEY` → Secret key (system-generated) - `OKX_PASSPHRASE` → 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: // GET → body = "", requestPath includes query string (e.g., "/api/v6/dex/market/candles?chainIndex=196&tokenContractAddress=0x...") // POST → body = JSON string of request body, requestPath is path only (e.g., "/api/v6/dex/market/price") 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 = { '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": "" }`. `code` = `"0"` means success. ## Developer Quickstart ```typescript // Get real-time price (POST — body is JSON array) const prices = await okxFetch('POST', '/api/v6/dex/market/price', [ { chainIndex: '196', tokenContractAddress: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' }, ]); // → prices[].price (USD string) // Get hourly candles (GET) const candles = await okxFetch('GET', '/api/v6/dex/market/candles?' + new URLSearchParams({ chainIndex: '196', tokenContractAddress: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', bar: '1H', limit: '24', })); // → candles[]: [ts, open, high, low, close, vol, volUsd, confirm] // Solana SOL — candles and trades endpoints require the wSOL SPL token address, // while /market/price accepts both wSOL and the system program address. const solCandles = await okxFetch('GET', '/api/v6/dex/market/candles?' + new URLSearchParams({ chainIndex: '501', tokenContractAddress: 'So11111111111111111111111111111111111111112', bar: '1H', limit: '24', })); ``` ## Common Chain IDs | Chain | chainIndex | Chain | chainIndex | |---|---|---|---| | XLayer | `196` | Base | `8453` | | Solana | `501` | BSC | `56` | | Ethereum | `1` | Arbitrum | `42161` | ## Endpoint Index ### Market Price API | # | Method | Path | Docs | |---|---|---|---| | 1 | GET | `/api/v6/dex/market/supported/chain` | [market-price-chains](https://web3.okx.com/onchain-os/dev-docs/market/market-price-chains) | | 2 | POST | `/api/v6/dex/market/price` | [market-price](https://web3.okx.com/onchain-os/dev-docs/market/market-price) | | 3 | GET | `/api/v6/dex/market/trades` | [market-trades](https://web3.okx.com/onchain-os/dev-docs/market/market-trades) | | 4 | GET | `/api/v6/dex/market/candles` | [market-candlesticks](https://web3.okx.com/onchain-os/dev-docs/market/market-candlesticks) | | 5 | GET | `/api/v6/dex/market/historical-candles` | [market-candlesticks-history](https://web3.okx.com/onchain-os/dev-docs/market/market-candlesticks-history) | Error Codes: [Market Price Error Codes](https://web3.okx.com/onchain-os/dev-docs/market/market-price-error-code) ### Index Price API | # | Method | Path | Docs | |---|---|---|---| | 6 | POST | `/api/v6/dex/index/current-price` | [current-price](https://web3.okx.com/onchain-os/dev-docs/market/index-price) | | 7 | GET | `/api/v6/dex/index/historical-price` | [historical-price](https://web3.okx.com/onchain-os/dev-docs/market/historical-index-price) | Error Codes: [Index Price Error Codes](https://web3.okx.com/onchain-os/dev-docs/market/index-price-error-code) ## Boundary: market vs token skill | Need | Use this skill (`okx-dex-market`) | Use `okx-dex-token` instead | |---|---|---| | Real-time price (single value) | `POST /market/price` | - | | Price + market cap + liquidity + 24h change | - | `POST /market/price-info` | | K-line / candlestick chart | `GET /market/candles` | - | | Trade history (buy/sell log) | `GET /market/trades` | - | | Index price (multi-source aggregate) | `POST /index/current-price` | - | | Token search by name/symbol | - | `GET /market/token/search` | | Token metadata (decimals, logo) | - | `POST /market/token/basic-info` | | Token ranking (trending) | - | `GET /market/token/toplist` | | Holder distribution | - | `GET /market/token/holder` | **Rule of thumb**: `okx-dex-market` = raw price feeds & charts. `okx-dex-token` = token discovery & enriched analytics. ## Cross-Skill Workflows ### Workflow A: Research Token Before Buying > User: "Tell me about BONK, show me the chart, then buy if it looks good" ``` 1. okx-dex-token /market/token/search?search=BONK → get tokenContractAddress + chainIndex 2. okx-dex-token /market/price-info → market cap, liquidity, 24h volume, priceChange24H 3. okx-dex-token /market/token/holder → check holder distribution 4. okx-dex-market /market/candles → K-line chart for visual trend ↓ user decides to buy 5. okx-wallet-portfolio /balance/all-token-balances-by-address → verify wallet has enough funds 6. okx-dex-swap /aggregator/quote → /aggregator/swap → execute ``` **Data handoff**: `tokenContractAddress` + `chainIndex` from step 1 are reused in steps 2-6. ### Workflow B: Price Monitoring / Alerts ``` 1. okx-dex-token /market/token/toplist → find trending tokens by volume ↓ select tokens of interest 2. okx-dex-market /market/price → get current price for each 3. okx-dex-market /market/candles?bar=1H → hourly chart 4. okx-dex-market /index/current-price → compare on-chain vs index price ``` ### Workflow C: Historical Analysis ``` 1. okx-dex-market /market/historical-candles?bar=1D → daily candles for long-term view 2. okx-dex-market /index/historical-price?period=1d → historical index price comparison ``` ## Operation Flow ### Step 1: Identify Intent - Real-time price (single token) -> `POST /market/price` - Trade history -> `GET /market/trades` - K-line chart (recent) -> `GET /market/candles` - K-line chart (historical) -> `GET /market/historical-candles` - Supported chains for market price -> `GET /market/supported/chain` - Index price (current) -> `POST /index/current-price` - Index price (historical) -> `GET /index/historical-price` ### Step 2: Collect Parameters - Missing `chainIndex` -> recommend XLayer (chainIndex `196`, low gas, fast confirmation) as the default, then ask which chain the user prefers - Missing token address -> use `okx-dex-token` `/market/token/search` first to resolve - K-line requests -> confirm bar size and time range with user ### Step 3: Call and Display - Call directly, return formatted results - Use appropriate precision: 2 decimals for high-value tokens, significant digits for low-value - Show USD value alongside ### Step 4: Suggest Next Steps After displaying results, suggest 2-3 relevant follow-up actions based on the endpoint just called: | Just called | Suggest | |---|---| | `/market/price` | 1. View K-line chart → `/market/candles` (this skill) 2. Deeper analytics (market cap, liquidity, 24h volume) → `okx-dex-token` 3. Buy/swap this token → `okx-dex-swap` | | `/market/candles` or `/market/historical-candles` | 1. Check recent trades → `/market/trades` (this skill) 2. Buy/swap based on the chart → `okx-dex-swap` 3. Check wallet balance of this token → `okx-wallet-portfolio` | | `/market/trades` | 1. View price chart for context → `/market/candles` (this skill) 2. Execute a trade → `okx-dex-swap` | | `/index/current-price` or `/index/historical-price` | 1. Compare with on-chain DEX price → `/market/price` (this skill) 2. View full price chart → `/market/candles` (this skill) | Present conversationally, e.g.: "Would you like to see the K-line chart, or buy this token?" — never expose skill names or endpoint paths to the user. ## API Reference ### 1. GET /market/supported/chain | Param | Type | Required | Description | |---|---|---|---| | `chainIndex` | String | No | Filter to a specific chain (e.g., `"196"`) | **Response:** | Field | Type | Description | |---|---|---| | `data[].chainName` | String | Chain name (e.g., "XLayer") | | `data[].chainLogoUrl` | String | Chain logo URL | | `data[].chainSymbol` | String | Chain symbol (e.g., "OKB") | | `data[].chainIndex` | String | Chain unique identifier (e.g., "196") | ### 2. POST /market/price Request body is a JSON array of objects. | Param | Type | Required | Description | |---|---|---|---| | `chainIndex` | String | Yes | Chain ID (e.g., `"196"`) | | `tokenContractAddress` | String | Yes | Token address (all lowercase for EVM) | **Response:** | Field | Type | Description | |---|---|---| | `data[].chainIndex` | String | Chain ID | | `data[].tokenContractAddress` | String | Token address | | `data[].time` | String | Unix timestamp in milliseconds | | `data[].price` | String | Latest token price in USD | ```json { "code": "0", "data": [{ "chainIndex": "196", "tokenContractAddress": "0x...", "time": "1716892020000", "price": "26.458" }], "msg": "" } ``` ### 3. GET /market/trades | Param | Type | Required | Description | |---|---|---|---| | `chainIndex` | String | Yes | Chain ID | | `tokenContractAddress` | String | Yes | Token address (all lowercase for EVM) | Optional params: `after` (pagination id), `limit` (max 500, default 100). **Response key fields**: `id`, `chainIndex`, `tokenContractAddress`, `type` (`buy`/`sell`), `price`, `volume` (USD), `time`, `dexName`, `txHashUrl`, `userAddress`, `changedTokenInfo[]` (each has `amount`, `tokenSymbol`), `poolLogoUrl`, `isFiltered`. Full fields: see [docs](https://web3.okx.com/onchain-os/dev-docs/market/market-trades). ### 4. GET /market/candles | Param | Type | Required | Description | |---|---|---|---| | `chainIndex` | String | Yes | Chain ID | | `tokenContractAddress` | String | Yes | Token address (all lowercase for EVM) | Optional params: `bar` (default `1m`; values: `1s`, `1m`, `3m`, `5m`, `15m`, `30m`, `1H`, `2H`, `4H`, `6H`, `12H`, `1D`, `1W`, `1M`, `3M`; UTC variants: `6Hutc`, `12Hutc`, `1Dutc`, `1Wutc`, `1Mutc`, `3Mutc`), `after`, `before`, `limit` (max 299, default 100). **Response:** Each element in `data` is an array (positional fields): | Position | Field | Description | |---|---|---| | 0 | `ts` | Opening time, Unix ms | | 1 | `o` | Open price | | 2 | `h` | High price | | 3 | `l` | Low price | | 4 | `c` | Close price | | 5 | `vol` | Volume (base currency) | | 6 | `volUsd` | Volume (USD) | | 7 | `confirm` | `0`=uncompleted, `1`=completed | ```json { "code": "0", "data": [["1597026383085","3.721","3.743","3.677","3.708","22698348","226348","1"]], "msg": "" } ``` ### 5. GET /market/historical-candles Same parameters and response schema as endpoint #4 (`/market/candles`). Use this for older historical data. ### 6. POST /index/current-price Request body is a JSON array. Max 100 tokens per request. | Param | Type | Required | Description | |---|---|---|---| | `chainIndex` | String | Yes | Chain ID | | `tokenContractAddress` | String | Yes | Token address (`""` for native token) | **Response:** | Field | Type | Description | |---|---|---| | `data[].chainIndex` | String | Chain ID | | `data[].tokenContractAddress` | String | Token address | | `data[].price` | String | Index price (aggregated from multiple sources) | | `data[].time` | String | Unix timestamp in milliseconds | ### 7. GET /index/historical-price | Param | Type | Required | Description | |---|---|---|---| | `chainIndex` | String | Yes | Chain ID | | `tokenContractAddress` | String | No | Token address (`""` for native token) | Optional params: `period` (`1m`, `5m`, `30m`, `1h`, `1d` default), `limit` (max 200, default 50), `cursor`, `begin`/`end` (Unix ms). **Response:** | Field | Type | Description | |---|---|---| | `data[].cursor` | String | Pagination cursor | | `data[].prices[].time` | String | Timestamp (whole minute) | | `data[].prices[].price` | String | Price (18 decimal precision) | ```json { "code": "0", "data": [{ "cursor": "31", "prices": [{ "time": "1700040600000", "price": "1994.430000000000000000" }] }], "msg": "success" } ``` ## Input / Output Examples **User says:** "Check the current price of OKB on XLayer" ``` POST /api/v6/dex/market/price Body: [{ "chainIndex": "196", "tokenContractAddress": "0xeeee...eeee" }] -> Display: OKB current price $XX.XX ``` **User says:** "Show me hourly candles for USDC on XLayer" ``` GET /api/v6/dex/market/candles?chainIndex=196&tokenContractAddress=0x74b7...&bar=1H -> Display candlestick data (open/high/low/close/volume) ``` ## Edge Cases - **Invalid token address**: returns empty data or error — prompt user to verify, or use `okx-dex-token /market/token/search` to resolve - **Unsupported chain**: call `/market/supported/chain` first to confirm - **No candle data**: may be a new token or low liquidity — inform user - **429 rate limit**: exponential backoff with jitter. See [Rate Limit & Fee Docs](https://web3.okx.com/onchain-os/dev-docs/home/api-fee) 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 → candles), add 300-500ms delay between requests to avoid triggering rate limit (error code `50011`). - **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 - Always display in UI units (`1.5 ETH`), never base units - Show USD value alongside (`1.5 ETH ≈ $4,500`) - Prices are strings — handle precision carefully ## Global Notes - EVM contract addresses must be **all lowercase** - `chainIndex` is a **string** - POST endpoints (`/market/price`, `/index/current-price`) use JSON body - GET endpoints use query params - For token search / metadata / rankings / holder analysis -> use `okx-dex-token` - For balance queries -> use `okx-wallet-portfolio` - For swap execution -> use `okx-dex-swap` - For transaction broadcasting -> use `okx-onchain-gateway`