BitMart Spot Trading
Overview
| # |
Category |
API Endpoint |
Type |
Description |
| 1 |
Market Data |
GET /spot/quotation/v3/ticker |
READ |
Get single pair ticker |
| 2 |
Market Data |
GET /spot/quotation/v3/tickers |
READ |
Get all pair tickers |
| 3 |
Market Data |
GET /spot/quotation/v3/books |
READ |
Order book depth (max 50) |
| 4 |
Market Data |
GET /spot/quotation/v3/trades |
READ |
Recent public trades (max 50) |
| 5 |
Market Data |
GET /spot/quotation/v3/klines |
READ |
Historical K-line/candlestick |
| 6 |
Market Data |
GET /spot/quotation/v3/lite-klines |
READ |
Latest K-line data |
| 7 |
Market Data |
GET /spot/v1/symbols/details |
READ |
Trading pair details |
| 8 |
Market Data |
GET /spot/v1/symbols |
READ |
Trading pair list |
| 9 |
Market Data |
GET /spot/v1/currencies |
READ |
All supported currencies |
| 10 |
Account |
GET /account/v1/wallet |
READ |
Account balance (all wallets) |
| 11 |
Account |
GET /spot/v1/wallet |
READ |
Spot wallet balance |
| 12 |
Account |
GET /spot/v1/trade_fee |
READ |
Actual trade fee rate |
| 13 |
Account |
GET /spot/v1/user_fee |
READ |
Base fee rate (account tier) |
| 14 |
Margin Account |
GET /spot/v1/margin/isolated/account |
READ |
Isolated margin account details |
| 15 |
Margin Account |
GET /spot/v1/margin/isolated/pairs |
READ |
Borrowing rate & amount |
| 16 |
Margin Account |
GET /spot/v1/margin/isolated/borrow_record |
READ |
Borrow record |
| 17 |
Margin Account |
GET /spot/v1/margin/isolated/repay_record |
READ |
Repayment record |
| 18 |
Trading |
POST /spot/v2/submit_order |
WRITE |
Place single order |
| 19 |
Trading |
POST /spot/v1/margin/submit_order |
WRITE |
Place margin order |
| 20 |
Trading |
POST /spot/v4/batch_orders |
WRITE |
Batch orders (max 10) |
| 21 |
Trading |
POST /spot/v3/cancel_order |
WRITE |
Cancel single order |
| 22 |
Trading |
POST /spot/v4/cancel_orders |
WRITE |
Cancel multiple orders |
| 23 |
Trading |
POST /spot/v4/cancel_all |
WRITE |
Cancel all open orders |
| 24 |
Order Query |
POST /spot/v4/query/order |
READ |
Query order by order ID |
| 25 |
Order Query |
POST /spot/v4/query/client-order |
READ |
Query by client order ID |
| 26 |
Order Query |
POST /spot/v4/query/open-orders |
READ |
All open orders |
| 27 |
Order Query |
POST /spot/v4/query/history-orders |
READ |
Historical orders |
| 28 |
Order Query |
POST /spot/v4/query/trades |
READ |
Account trade history |
| 29 |
Order Query |
POST /spot/v4/query/order-trades |
READ |
Trades for specific order |
| 30 |
Margin Loan |
POST /spot/v1/margin/isolated/borrow |
WRITE |
Margin borrow (isolated) |
| 31 |
Margin Loan |
POST /spot/v1/margin/isolated/repay |
WRITE |
Margin repay (isolated) |
| 32 |
Margin Loan |
POST /spot/v1/margin/isolated/transfer |
WRITE |
Margin asset transfer |
| 33 |
System |
GET /system/time |
READ |
Get server time (milliseconds) |
| 34 |
System |
GET /system/service |
READ |
Get system service status / maintenance |
Skill Routing
| User Intent |
Correct Skill |
| Spot buy/sell, order management, balance, fee rates |
bitmart-exchange-spot (this skill) |
| Futures/contract trading, leverage, TP/SL, plan orders |
bitmart-exchange-futures |
Authentication
Credential Check (Before Any Private API Call)
Before calling any authenticated endpoint, verify credentials are available:
- Check for environment variables:
BITMART_API_KEY — API key
BITMART_API_SECRET — Secret key
BITMART_API_MEMO — Memo string
- Or check for config file:
~/.bitmart/config.toml[default]
api_key = "your-api-key"
api_secret = "your-secret-key"
memo = "your-memo"
- If missing: STOP. Guide user to set up credentials. Do NOT proceed with any authenticated call.
Key display rules: When displaying credentials back to the user, show only the first 5 and last 4 characters (e.g., bmk12...9xyz). NEVER display full secret or memo values.
Auth Levels
| Level |
When |
Headers Required |
| NONE |
Public market data (endpoints 1-9) |
None |
| KEYED |
Read-only private data — balances, fees, margin account, borrow/repay records (endpoints 10-17) |
X-BM-KEY |
| SIGNED |
Write operations and order queries (endpoints 18-32) |
X-BM-KEY + X-BM-SIGN + X-BM-TIMESTAMP |
Signature Generation
timestamp = current UTC time in milliseconds
message = "{timestamp}#{memo}#{request_body_json}"
signature = HMAC-SHA256(secret_key, message) → hex string
- For POST requests:
request_body_json is the JSON body string.
- For GET requests:
request_body_json is an empty string "".
Required Headers (SIGNED)
| Header |
Value |
Content-Type |
application/json |
X-BM-KEY |
API key |
X-BM-SIGN |
Hex-encoded HMAC-SHA256 signature |
X-BM-TIMESTAMP |
Current UTC timestamp in milliseconds |
User-Agent |
bitmart-skills/spot/v2026.3.23 — identifies requests from this skill for analytics |
See references/authentication.md for full setup guide and troubleshooting.
API Base
- Base URL:
https://api-cloud.bitmart.com
- Symbol Format:
BTC_USDT (base_quote, underscore separated)
Standard Response Format
Success:
{
"code": 1000,
"message": "OK",
"trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": { ... }
}
Error:
{
"code": 50000,
"message": "Bad Request",
"trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": null
}
Important: code == 1000 means success. Any other code is an error.
Important: Spot business error codes are endpoint/version specific. Do not assume the same numeric code has the same meaning across all spot flows.
GET requests: Parameters go in the query string.
POST requests: Parameters go in the JSON body.
Rate Limits
| Endpoint |
Rate |
Target |
GET /spot/quotation/v3/ticker |
15 req/2sec |
IP |
GET /spot/quotation/v3/tickers |
10 req/2sec |
IP |
GET /spot/quotation/v3/lite-klines |
15 req/2sec |
IP |
GET /spot/quotation/v3/klines |
10 req/2sec |
IP |
GET /spot/quotation/v3/books |
15 req/2sec |
IP |
GET /spot/quotation/v3/trades |
15 req/2sec |
IP |
GET /spot/v1/currencies |
8 req/2sec |
IP |
GET /spot/v1/symbols |
8 req/2sec |
IP |
GET /spot/v1/symbols/details |
12 req/2sec |
IP |
| Balance |
12 req/2sec |
KEY |
| Trade Fee / User Fee |
2 req/2sec |
KEY |
| Margin Account |
12 req/2sec |
KEY |
| Margin Pairs |
2 req/2sec |
KEY |
| Borrow / Repay Records |
150 req/2sec |
KEY |
| Place Order (spot) |
40 req/2sec |
UID |
Batch Place Orders (/spot/v4/batch_orders) |
40 req/2sec |
UID |
| Place Order (margin) |
20 req/1sec |
UID |
| Cancel Order |
40 req/2sec |
UID |
Cancel Multiple (/spot/v4/cancel_orders) |
40 req/2sec |
UID |
| Cancel All |
1 req/3sec |
UID |
| Query Order by ID |
50 req/2sec |
KEY |
Query by Client Order ID (/spot/v4/query/client-order) |
50 req/2sec |
KEY |
| Open / History / Trades |
12 req/2sec |
KEY |
| Order-Trades |
12 req/2sec |
KEY |
| Margin Borrow / Repay / Transfer |
2 req/2sec |
KEY |
GET /system/time |
10 req/sec |
IP |
GET /system/service |
10 req/sec |
IP |
Rate limit response headers:
X-BM-RateLimit-Remaining — Number of requests already used in the current window
X-BM-RateLimit-Limit — Maximum allowed requests in the current window
X-BM-RateLimit-Reset — Current time window length (seconds)
Warning: If X-BM-RateLimit-Remaining >= X-BM-RateLimit-Limit, stop calling immediately and wait for reset to avoid sending one extra over-limit request.
If rate limited (HTTP 429), wait for the reset period before retrying.
Quickstart
Example 1: Get BTC price (no auth)
curl -s -H "User-Agent: bitmart-skills/spot/v2026.3.23" 'https://api-cloud.bitmart.com/spot/quotation/v3/ticker?symbol=BTC_USDT'
Example 2: Get account balance (KEYED)
curl -s -H "X-BM-KEY: $BITMART_API_KEY" \
-H "User-Agent: bitmart-skills/spot/v2026.3.23" \
'https://api-cloud.bitmart.com/account/v1/wallet'
Example 3: Place limit buy order (SIGNED)
TIMESTAMP=$(date +%s000)
BODY='{"symbol":"BTC_USDT","side":"buy","type":"limit","size":"0.001","price":"60000"}'
SIGN=$(echo -n "${TIMESTAMP}#${BITMART_API_MEMO}#${BODY}" | openssl dgst -sha256 -hmac "$BITMART_API_SECRET" | awk '{print $NF}')
curl -s -X POST 'https://api-cloud.bitmart.com/spot/v2/submit_order' \
-H "User-Agent: bitmart-skills/spot/v2026.3.23" \
-H "Content-Type: application/json" \
-H "X-BM-KEY: $BITMART_API_KEY" \
-H "X-BM-SIGN: $SIGN" \
-H "X-BM-TIMESTAMP: $TIMESTAMP" \
-d "$BODY"
API Reference
See references/api-reference.md for full endpoint documentation with parameters, examples, and response formats.
See references/scenarios.md for step-by-step execution flows for common spot tasks such as market buy, limit sell, batch orders, and cancel-replace.
Reference: Order Types
| Type |
Description |
limit |
Execute at specified price or better |
market |
Execute immediately at best available price |
limit_maker |
Post-only; rejected if it would immediately match (ensures maker fee) |
ioc |
Immediate-or-cancel; unfilled portion is canceled immediately |
Reference: Order Sides
| Side |
Description |
buy |
Buy base currency with quote currency |
sell |
Sell base currency for quote currency |
Reference: Order States
| State |
Description |
new |
Order accepted, not yet filled |
partially_filled |
Partially executed, still open |
filled |
Fully executed |
canceled |
Canceled by user |
partially_canceled |
Partially filled, then canceled |
Reference: Cancel Sources
| Source |
Description |
"" (empty) |
Not canceled |
user |
Canceled by user |
system |
Canceled by system (e.g., insufficient balance) |
stp |
Canceled by self-trade prevention |
Reference: STP Modes
| Mode |
Description |
none |
No self-trade prevention |
cancel_maker |
Cancel the resting (maker) order if self-trade detected |
cancel_taker |
Cancel the incoming (taker) order if self-trade detected |
cancel_both |
Cancel both orders if self-trade detected |
Reference: Trade Roles
| Role |
Description |
taker |
Order matched immediately against resting order |
maker |
Order rested on book and was matched later |
Reference: Parameter Naming Convention
CRITICAL — Wrong case = silently ignored field. The API does NOT return an error for misnamed params; it simply ignores them, causing unexpected behavior or wrong results. Always verify the endpoint version before constructing any request body.
| API Version |
Convention |
Examples |
| v1-v3 |
snake_case |
client_order_id, order_id, start_time |
| v4 |
camelCase |
clientOrderId, orderId, orderMode, startTime |
Mixed-case exceptions (must be memorized):
POST /spot/v2/submit_order: stpMode (camelCase) alongside client_order_id (snake_case)
POST /spot/v1/margin/submit_order: clientOrderId (camelCase in a v1 endpoint)
Reference: K-Line Steps
| Step (minutes) |
Description |
| 1 |
1-minute candles |
| 5 |
5-minute candles |
| 15 |
15-minute candles |
| 30 |
30-minute candles |
| 60 |
1-hour candles |
| 120 |
2-hour candles |
| 240 |
4-hour candles |
| 1440 |
1-day candles |
| 10080 |
1-week candles |
| 43200 |
1-month candles |
Operation Flow
Step 0: Credential Check
Verify BITMART_API_KEY, BITMART_API_SECRET, and BITMART_API_MEMO are available via environment variables or ~/.bitmart/config.toml. If missing, STOP and guide the user to set up credentials.
Step 1: Identify User Intent
Parse user request and map to a READ or WRITE operation:
- READ operations: market data, balance queries, order queries, fee rates
- WRITE operations: place order, cancel order, batch orders
Timestamp Display Rules
API responses contain Unix timestamps in different units. When displaying any timestamp to the user, always convert to human-readable local time.
| Field |
Unit |
Conversion |
createTime, updateTime (order responses) |
Milliseconds |
÷ 1000 → Unix seconds → local time |
server_time (system time) |
Milliseconds |
÷ 1000 → Unix seconds → local time |
t (K-line candle open time) |
Seconds |
Direct → Unix seconds → local time |
create_time (borrow records) |
Seconds |
Direct → Unix seconds → local time |
repay_time (repay records) |
Seconds |
Direct → Unix seconds → local time |
Display format: YYYY-MM-DD HH:MM:SS in the user's local timezone. Example: timestamp 1700000000000 (ms) → 2023-11-15 06:13:20 (UTC+8).
Common mistakes to avoid:
- Do NOT treat millisecond timestamps as seconds (produces dates in year 55000+)
- Do NOT display raw numeric timestamps — always convert to readable format
- Do NOT assume UTC — convert to the user's local timezone
Step 2: Execute
READ: Call the API endpoint, parse response, format data for user display.
WRITE: Follow these sub-steps strictly in order:
2a. Parameter naming check (prevents silent failures):
- Identify the API version of the target endpoint
- v4 endpoints (
/spot/v4/...): ALL params must be camelCase (clientOrderId, orderId, orderMode, startTime)
- v1–v3 endpoints: ALL params must be snake_case (
client_order_id, order_id, start_time)
- Special exception:
POST /spot/v2/submit_order uses mixed — client_order_id (snake_case) + stpMode (camelCase)
- The API does NOT return an error for wrong-case params — it silently ignores them, causing wrong orders or failed queries
2b. Order type rules — params, precision, minimum validation:
First call GET /spot/v1/symbols/details, locate the symbol in data.symbols[], extract: price_max_precision, quote_increment, min_buy_amount, min_sell_amount.
Then branch:
type=market, side=buy — Market buy:
- Send only
notional (USDT/quote amount). Do NOT send size or price — silently ignored and causes error 50021.
- Validate:
float(notional) >= min_buy_amount. If not, STOP — suggest "notional":"<min_buy_amount>". API returns 51012 otherwise.
- Body:
{"symbol":"XRP_USDT","side":"buy","type":"market","notional":"5"}
type=market, side=sell — Market sell:
- Send only
size (base currency quantity, e.g. XRP amount). Do NOT send price or notional.
- Truncate
size to quote_increment precision.
- Estimate value:
size * current_last_price. If estimated value < min_sell_amount, STOP and warn user.
- Body:
{"symbol":"XRP_USDT","side":"sell","type":"market","size":"10"}
type=limit — Limit order:
- Send
size + price. Truncate price to price_max_precision, size to quote_increment.
- Note: If price exceeds
price_max_precision, the API silently truncates the extra decimals instead of returning an error. Always truncate client-side to ensure the submitted price matches the intended price.
- Calculate
order_value = size * price. If order_value < min_buy_amount (buy) or < min_sell_amount (sell), STOP.
- If user requested "buy all" / "use full balance":
size = floor(balance / price) at precision, re-verify minimum.
- No hidden risk — order sits on the book until filled or canceled.
type=limit_maker — Post-only (maker-only):
- Same params as
limit (size + price). Same precision/minimum rules.
- CRITICAL behavioral note: The server auto-cancels the order (no error) if the price would immediately match:
- Buy
limit_maker: if price >= best_ask, order is silently canceled. Price must be below best ask.
- Sell
limit_maker: if price <= best_bid, order is silently canceled. Price must be above best bid.
- Inform user of this risk when setting an aggressive
limit_maker price.
type=ioc — Immediate-or-Cancel:
- Same params as
limit (size + price). Same precision/minimum rules.
- Behavioral note: Fills whatever quantity is available immediately at the given price; the unfilled remainder is immediately canceled. User may receive a partial fill or no fill at all.
2c. Confirm and execute:
- Present order summary based on type:
- market buy: symbol, side=buy, type=market, notional amount
- market sell: symbol, side=sell, type=market, size (quantity)
- limit/limit_maker/ioc: symbol, side, type, size, price, estimated order value
- For
limit_maker: include a reminder that the order will be auto-canceled if the price crosses the spread.
- Ask for explicit "CONFIRM" before executing. Only proceed after user confirms.
Step 3: Verify (WRITE only)
- After placing an order: Call
POST /spot/v4/query/order with {"orderId":"..."} to confirm order status.
- After canceling an order: Call
POST /spot/v4/query/open-orders to verify the order is no longer open.
- Report the verified result to the user.
Cross-Skill Workflows
Workflow 1: Check Price → Check Balance → Buy
- bitmart-exchange-spot →
GET /spot/quotation/v3/ticker?symbol=BTC_USDT — Get current price
- bitmart-exchange-spot →
GET /account/v1/wallet — Check available balance
- bitmart-exchange-spot →
POST /spot/v2/submit_order — Place buy order (after user CONFIRM)
- bitmart-exchange-spot →
POST /spot/v4/query/order — Verify order execution
Error Handling
Spot business error codes are endpoint/version specific. Use the table below for authentication / transport issues and common current spot order-query behavior. For margin borrow / repay / transfer flows, see the margin-only notes after the table.
| Code |
Description |
Action |
| 1000 |
Success |
Process response normally |
| 30002 |
X-BM-KEY not found |
Check that API key is set correctly |
| 30005 |
X-BM-SIGN is wrong |
Verify signature generation (timestamp, memo, body format) |
| 30006 |
X-BM-TIMESTAMP is wrong |
Ensure X-BM-TIMESTAMP is present and is a Unix timestamp in milliseconds |
| 30007 |
Timestamp/recvWindow validation failed |
Sync system clock (NTP), send X-BM-TIMESTAMP as Unix milliseconds, and ensure (serverTime - timestamp) <= recvWindow; recvWindow must be Long in (0,60000], default 5000 (max 60000). For current signed v4 flows, rely on recvWindow as the effective request-validity window. |
| 30010 |
IP forbidden |
Check API key IP whitelist settings |
| 30013 |
Rate limit exceeded |
Wait for rate limit window to reset, then retry |
| 50005 |
Order Id not found / query returned no data |
On POST /spot/v4/query/order, a missing orderId / clientOrderId currently returns this code |
| 50021 |
param error |
For market buy, use notional (USDT amount) — do NOT use size; size is silently ignored and causes this error |
| 51011 |
param not match : size * price >= X |
Read symbol constraints from GET /spot/v1/symbols/details; enforce side-specific minimum notional (min_buy_amount/min_sell_amount) |
| 51012 |
below minimum order amount |
notional (for market buy) or size * price (for limit) is below min_buy_amount; increase order value to at least the symbol minimum |
| 52000 |
Unsupported OrderMode Type |
On current v4 query endpoints, use a valid orderMode (spot / iso_margin) or omit the field to query all modes |
| 40044 |
Invalid order size |
Call GET /spot/v1/symbols/details; use symbol precision/increment fields and truncate (not round) size and price |
| 50023 |
Operation is limited |
Pair may not support API trading; use a different pair |
| 429 |
HTTP rate limit |
Back off exponentially, check X-BM-RateLimit-Reset header |
| 418 |
IP banned |
Stop all requests immediately; wait before retrying |
Margin-only business codes (do not treat as global spot codes):
51003 — Account Limit. Use in margin borrow / repay / transfer context; do not use as the generic “order not found” code for v4 order-query flows.
51006 — Exceeds the amount to be repaid. Use for isolated margin repay flows.
51007 — order_mode not found in the official business-code table. Do not use this as guidance for current v4 query endpoints; invalid orderMode requests currently return 52000.
| 403 | Cloudflare WAF block | Check IP reputation (VPN/cloud IPs are commonly challenged); wait 30-60 seconds and retry; do not auto-retry more than 3 times |
| 503 | Cloudflare challenge / origin unavailable | Same as 403; if response body contains "Cloudflare" or "cf-", it is a Cloudflare interception, not a BitMart error; check network environment |
Cloudflare Handling
BitMart API is behind Cloudflare CDN. If you receive HTTP 403/503 and the response body contains "Cloudflare", "cf-", or an HTML challenge page (instead of JSON):
- This is a Cloudflare interception, not a BitMart API error — do not parse as JSON
- Check if too many requests were sent in a short window (Cloudflare WAF has its own rules independent of API rate limits)
- Wait 30-60 seconds before retrying
- If running from a cloud server or VPN, the IP may have low reputation — try from a different network
- Do not auto-retry more than 3 times — inform the user if the issue persists
Cloudflare 1010: Non-curl HTTP clients with default bot-like User-Agent strings (e.g., Python-urllib, Go-http-client) may receive HTTP 403 / error 1010. Always send the User-Agent: bitmart-skills/spot/v2026.3.23 header from your HTTP library — do not rely on the library default.
Security Notes
- Never display full API keys or secrets. Show first 5 + last 4 characters only (e.g.,
bmk12...9xyz).
- All WRITE operations require explicit user confirmation before execution. Present a clear summary of the action and wait for "CONFIRM".
- Recommend IP whitelist on API keys for additional security.
- Recommend minimum permissions: Read-Only + Spot-Trade only (no Withdraw permission).
- All trading outputs include disclaimer: "Not financial advice. You are solely responsible for your investment decisions."
1---2name: bitmart-exchange-spot3description: Use when the user asks about BitMart spot trading, including buying or selling crypto, placing limit or market orders, checking spot balance, querying open orders, viewing trade history, or managing margin positions. Do NOT use for futures/contract trading (use bitmart-exchange-futures).4---56# BitMart Spot Trading78## Overview910| # | Category | API Endpoint | Type | Description |11|---|----------|-------------|------|-------------|12| 1 | Market Data | `GET /spot/quotation/v3/ticker` | READ | Get single pair ticker |13| 2 | Market Data | `GET /spot/quotation/v3/tickers` | READ | Get all pair tickers |14| 3 | Market Data | `GET /spot/quotation/v3/books` | READ | Order book depth (max 50) |15| 4 | Market Data | `GET /spot/quotation/v3/trades` | READ | Recent public trades (max 50) |16| 5 | Market Data | `GET /spot/quotation/v3/klines` | READ | Historical K-line/candlestick |17| 6 | Market Data | `GET /spot/quotation/v3/lite-klines` | READ | Latest K-line data |18| 7 | Market Data | `GET /spot/v1/symbols/details` | READ | Trading pair details |19| 8 | Market Data | `GET /spot/v1/symbols` | READ | Trading pair list |20| 9 | Market Data | `GET /spot/v1/currencies` | READ | All supported currencies |21| 10 | Account | `GET /account/v1/wallet` | READ | Account balance (all wallets) |22| 11 | Account | `GET /spot/v1/wallet` | READ | Spot wallet balance |23| 12 | Account | `GET /spot/v1/trade_fee` | READ | Actual trade fee rate |24| 13 | Account | `GET /spot/v1/user_fee` | READ | Base fee rate (account tier) |25| 14 | Margin Account | `GET /spot/v1/margin/isolated/account` | READ | Isolated margin account details |26| 15 | Margin Account | `GET /spot/v1/margin/isolated/pairs` | READ | Borrowing rate & amount |27| 16 | Margin Account | `GET /spot/v1/margin/isolated/borrow_record` | READ | Borrow record |28| 17 | Margin Account | `GET /spot/v1/margin/isolated/repay_record` | READ | Repayment record |29| 18 | Trading | `POST /spot/v2/submit_order` | WRITE | Place single order |30| 19 | Trading | `POST /spot/v1/margin/submit_order` | WRITE | Place margin order |31| 20 | Trading | `POST /spot/v4/batch_orders` | WRITE | Batch orders (max 10) |32| 21 | Trading | `POST /spot/v3/cancel_order` | WRITE | Cancel single order |33| 22 | Trading | `POST /spot/v4/cancel_orders` | WRITE | Cancel multiple orders |34| 23 | Trading | `POST /spot/v4/cancel_all` | WRITE | Cancel all open orders |35| 24 | Order Query | `POST /spot/v4/query/order` | READ | Query order by order ID |36| 25 | Order Query | `POST /spot/v4/query/client-order` | READ | Query by client order ID |37| 26 | Order Query | `POST /spot/v4/query/open-orders` | READ | All open orders |38| 27 | Order Query | `POST /spot/v4/query/history-orders` | READ | Historical orders |39| 28 | Order Query | `POST /spot/v4/query/trades` | READ | Account trade history |40| 29 | Order Query | `POST /spot/v4/query/order-trades` | READ | Trades for specific order |41| 30 | Margin Loan | `POST /spot/v1/margin/isolated/borrow` | WRITE | Margin borrow (isolated) |42| 31 | Margin Loan | `POST /spot/v1/margin/isolated/repay` | WRITE | Margin repay (isolated) |43| 32 | Margin Loan | `POST /spot/v1/margin/isolated/transfer` | WRITE | Margin asset transfer |44| 33 | System | `GET /system/time` | READ | Get server time (milliseconds) |45| 34 | System | `GET /system/service` | READ | Get system service status / maintenance |4647---4849## Skill Routing5051| User Intent | Correct Skill |52|------------|---------------|53| Spot buy/sell, order management, balance, fee rates | **bitmart-exchange-spot** (this skill) |54| Futures/contract trading, leverage, TP/SL, plan orders | bitmart-exchange-futures |5556---5758## Authentication5960### Credential Check (Before Any Private API Call)6162Before calling any authenticated endpoint, verify credentials are available:63641. Check for environment variables:65 - `BITMART_API_KEY` — API key66 - `BITMART_API_SECRET` — Secret key67 - `BITMART_API_MEMO` — Memo string682. Or check for config file: `~/.bitmart/config.toml`69 ```toml70 [default]71 api_key = "your-api-key"72 api_secret = "your-secret-key"73 memo = "your-memo"74 ```753. If missing: **STOP**. Guide user to set up credentials. Do NOT proceed with any authenticated call.7677**Key display rules:** When displaying credentials back to the user, show only the first 5 and last 4 characters (e.g., `bmk12...9xyz`). NEVER display full secret or memo values.7879### Auth Levels8081| Level | When | Headers Required |82|-------|------|-----------------|83| **NONE** | Public market data (endpoints 1-9) | None |84| **KEYED** | Read-only private data — balances, fees, margin account, borrow/repay records (endpoints 10-17) | `X-BM-KEY` |85| **SIGNED** | Write operations and order queries (endpoints 18-32) | `X-BM-KEY` + `X-BM-SIGN` + `X-BM-TIMESTAMP` |8687### Signature Generation8889```90timestamp = current UTC time in milliseconds91message = "{timestamp}#{memo}#{request_body_json}"92signature = HMAC-SHA256(secret_key, message) → hex string93```9495- For **POST** requests: `request_body_json` is the JSON body string.96- For **GET** requests: `request_body_json` is an empty string `""`.9798### Required Headers (SIGNED)99100| Header | Value |101|--------|-------|102| `Content-Type` | `application/json` |103| `X-BM-KEY` | API key |104| `X-BM-SIGN` | Hex-encoded HMAC-SHA256 signature |105| `X-BM-TIMESTAMP` | Current UTC timestamp in milliseconds |106| `User-Agent` | `bitmart-skills/spot/v2026.3.23` — identifies requests from this skill for analytics |107108See `references/authentication.md` for full setup guide and troubleshooting.109110---111112## API Base113114- **Base URL**: `https://api-cloud.bitmart.com`115- **Symbol Format**: `BTC_USDT` (base_quote, underscore separated)116117## Standard Response Format118119**Success:**120```json121{122 "code": 1000,123 "message": "OK",124 "trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",125 "data": { ... }126}127```128129**Error:**130```json131{132 "code": 50000,133 "message": "Bad Request",134 "trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",135 "data": null136}137```138139**Important:** `code == 1000` means success. Any other code is an error.140**Important:** Spot business error codes are endpoint/version specific. Do **not** assume the same numeric code has the same meaning across all spot flows.141142**GET requests:** Parameters go in the query string.143**POST requests:** Parameters go in the JSON body.144145---146147## Rate Limits148149| Endpoint | Rate | Target |150|----------|------|--------|151| `GET /spot/quotation/v3/ticker` | 15 req/2sec | IP |152| `GET /spot/quotation/v3/tickers` | 10 req/2sec | IP |153| `GET /spot/quotation/v3/lite-klines` | 15 req/2sec | IP |154| `GET /spot/quotation/v3/klines` | 10 req/2sec | IP |155| `GET /spot/quotation/v3/books` | 15 req/2sec | IP |156| `GET /spot/quotation/v3/trades` | 15 req/2sec | IP |157| `GET /spot/v1/currencies` | 8 req/2sec | IP |158| `GET /spot/v1/symbols` | 8 req/2sec | IP |159| `GET /spot/v1/symbols/details` | 12 req/2sec | IP |160| Balance | 12 req/2sec | KEY |161| Trade Fee / User Fee | 2 req/2sec | KEY |162| Margin Account | 12 req/2sec | KEY |163| Margin Pairs | 2 req/2sec | KEY |164| Borrow / Repay Records | 150 req/2sec | KEY |165| Place Order (spot) | 40 req/2sec | UID |166| Batch Place Orders (`/spot/v4/batch_orders`) | 40 req/2sec | UID |167| Place Order (margin) | 20 req/1sec | UID |168| Cancel Order | 40 req/2sec | UID |169| Cancel Multiple (`/spot/v4/cancel_orders`) | 40 req/2sec | UID |170| Cancel All | 1 req/3sec | UID |171| Query Order by ID | 50 req/2sec | KEY |172| Query by Client Order ID (`/spot/v4/query/client-order`) | 50 req/2sec | KEY |173| Open / History / Trades | 12 req/2sec | KEY |174| Order-Trades | 12 req/2sec | KEY |175| Margin Borrow / Repay / Transfer | 2 req/2sec | KEY |176| `GET /system/time` | 10 req/sec | IP |177| `GET /system/service` | 10 req/sec | IP |178179**Rate limit response headers:**180- `X-BM-RateLimit-Remaining` — Number of requests already used in the current window181- `X-BM-RateLimit-Limit` — Maximum allowed requests in the current window182- `X-BM-RateLimit-Reset` — Current time window length (seconds)183184**Warning:** If `X-BM-RateLimit-Remaining >= X-BM-RateLimit-Limit`, stop calling immediately and wait for reset to avoid sending one extra over-limit request.185186If rate limited (HTTP 429), wait for the reset period before retrying.187188---189190## Quickstart191192### Example 1: Get BTC price (no auth)193194```bash195curl -s -H "User-Agent: bitmart-skills/spot/v2026.3.23" 'https://api-cloud.bitmart.com/spot/quotation/v3/ticker?symbol=BTC_USDT'196```197198### Example 2: Get account balance (KEYED)199200```bash201curl -s -H "X-BM-KEY: $BITMART_API_KEY" \202 -H "User-Agent: bitmart-skills/spot/v2026.3.23" \203 'https://api-cloud.bitmart.com/account/v1/wallet'204```205206### Example 3: Place limit buy order (SIGNED)207208```bash209TIMESTAMP=$(date +%s000)210BODY='{"symbol":"BTC_USDT","side":"buy","type":"limit","size":"0.001","price":"60000"}'211SIGN=$(echo -n "${TIMESTAMP}#${BITMART_API_MEMO}#${BODY}" | openssl dgst -sha256 -hmac "$BITMART_API_SECRET" | awk '{print $NF}')212curl -s -X POST 'https://api-cloud.bitmart.com/spot/v2/submit_order' \213 -H "User-Agent: bitmart-skills/spot/v2026.3.23" \214 -H "Content-Type: application/json" \215 -H "X-BM-KEY: $BITMART_API_KEY" \216 -H "X-BM-SIGN: $SIGN" \217 -H "X-BM-TIMESTAMP: $TIMESTAMP" \218 -d "$BODY"219```220221---222223## API Reference224225See `references/api-reference.md` for full endpoint documentation with parameters, examples, and response formats.226See `references/scenarios.md` for step-by-step execution flows for common spot tasks such as market buy, limit sell, batch orders, and cancel-replace.227228---229230## Reference: Order Types231232| Type | Description |233|------|-------------|234| `limit` | Execute at specified price or better |235| `market` | Execute immediately at best available price |236| `limit_maker` | Post-only; rejected if it would immediately match (ensures maker fee) |237| `ioc` | Immediate-or-cancel; unfilled portion is canceled immediately |238239## Reference: Order Sides240241| Side | Description |242|------|-------------|243| `buy` | Buy base currency with quote currency |244| `sell` | Sell base currency for quote currency |245246## Reference: Order States247248| State | Description |249|-------|-------------|250| `new` | Order accepted, not yet filled |251| `partially_filled` | Partially executed, still open |252| `filled` | Fully executed |253| `canceled` | Canceled by user |254| `partially_canceled` | Partially filled, then canceled |255256## Reference: Cancel Sources257258| Source | Description |259|--------|-------------|260| `""` (empty) | Not canceled |261| `user` | Canceled by user |262| `system` | Canceled by system (e.g., insufficient balance) |263| `stp` | Canceled by self-trade prevention |264265## Reference: STP Modes266267| Mode | Description |268|------|-------------|269| `none` | No self-trade prevention |270| `cancel_maker` | Cancel the resting (maker) order if self-trade detected |271| `cancel_taker` | Cancel the incoming (taker) order if self-trade detected |272| `cancel_both` | Cancel both orders if self-trade detected |273274## Reference: Trade Roles275276| Role | Description |277|------|-------------|278| `taker` | Order matched immediately against resting order |279| `maker` | Order rested on book and was matched later |280281## Reference: Parameter Naming Convention282283> **CRITICAL — Wrong case = silently ignored field.** The API does NOT return an error for misnamed params; it simply ignores them, causing unexpected behavior or wrong results. Always verify the endpoint version before constructing any request body.284285| API Version | Convention | Examples |286|-------------|-----------|----------|287| v1-v3 | snake_case | `client_order_id`, `order_id`, `start_time` |288| v4 | camelCase | `clientOrderId`, `orderId`, `orderMode`, `startTime` |289290**Mixed-case exceptions (must be memorized):**291- `POST /spot/v2/submit_order`: `stpMode` (camelCase) alongside `client_order_id` (snake_case)292- `POST /spot/v1/margin/submit_order`: `clientOrderId` (camelCase in a v1 endpoint)293294## Reference: K-Line Steps295296| Step (minutes) | Description |297|----------------|-------------|298| 1 | 1-minute candles |299| 5 | 5-minute candles |300| 15 | 15-minute candles |301| 30 | 30-minute candles |302| 60 | 1-hour candles |303| 120 | 2-hour candles |304| 240 | 4-hour candles |305| 1440 | 1-day candles |306| 10080 | 1-week candles |307| 43200 | 1-month candles |308309---310311## Operation Flow312313### Step 0: Credential Check314315Verify `BITMART_API_KEY`, `BITMART_API_SECRET`, and `BITMART_API_MEMO` are available via environment variables or `~/.bitmart/config.toml`. If missing, STOP and guide the user to set up credentials.316317### Step 1: Identify User Intent318319Parse user request and map to a READ or WRITE operation:320321- **READ** operations: market data, balance queries, order queries, fee rates322- **WRITE** operations: place order, cancel order, batch orders323324### Timestamp Display Rules325326API responses contain Unix timestamps in different units. When displaying any timestamp to the user, **always convert to human-readable local time**.327328| Field | Unit | Conversion |329|-------|------|------------|330| `createTime`, `updateTime` (order responses) | Milliseconds | `÷ 1000` → Unix seconds → local time |331| `server_time` (system time) | Milliseconds | `÷ 1000` → Unix seconds → local time |332| `t` (K-line candle open time) | Seconds | Direct → Unix seconds → local time |333| `create_time` (borrow records) | Seconds | Direct → Unix seconds → local time |334| `repay_time` (repay records) | Seconds | Direct → Unix seconds → local time |335336**Display format:** `YYYY-MM-DD HH:MM:SS` in the user's local timezone. Example: timestamp `1700000000000` (ms) → `2023-11-15 06:13:20` (UTC+8).337338**Common mistakes to avoid:**339- Do NOT treat millisecond timestamps as seconds (produces dates in year 55000+)340- Do NOT display raw numeric timestamps — always convert to readable format341- Do NOT assume UTC — convert to the user's local timezone342343### Step 2: Execute344345- **READ**: Call the API endpoint, parse response, format data for user display.346- **WRITE**: Follow these sub-steps strictly in order:347348 **2a. Parameter naming check (prevents silent failures):**349 - Identify the API version of the target endpoint350 - v4 endpoints (`/spot/v4/...`): ALL params must be **camelCase** (`clientOrderId`, `orderId`, `orderMode`, `startTime`)351 - v1–v3 endpoints: ALL params must be **snake_case** (`client_order_id`, `order_id`, `start_time`)352 - Special exception: `POST /spot/v2/submit_order` uses **mixed** — `client_order_id` (snake_case) + `stpMode` (camelCase)353 - The API does NOT return an error for wrong-case params — it silently ignores them, causing wrong orders or failed queries354355 **2b. Order type rules — params, precision, minimum validation:**356357 First call `GET /spot/v1/symbols/details`, locate the symbol in `data.symbols[]`, extract: `price_max_precision`, `quote_increment`, `min_buy_amount`, `min_sell_amount`.358359 Then branch:360361 **`type=market`, `side=buy` — Market buy:**362 - Send only `notional` (USDT/quote amount). Do NOT send `size` or `price` — silently ignored and causes error 50021.363 - Validate: `float(notional) >= min_buy_amount`. If not, STOP — suggest `"notional":"<min_buy_amount>"`. API returns 51012 otherwise.364 - Body: `{"symbol":"XRP_USDT","side":"buy","type":"market","notional":"5"}`365366 **`type=market`, `side=sell` — Market sell:**367 - Send only `size` (base currency quantity, e.g. XRP amount). Do NOT send `price` or `notional`.368 - Truncate `size` to `quote_increment` precision.369 - Estimate value: `size * current_last_price`. If estimated value `< min_sell_amount`, STOP and warn user.370 - Body: `{"symbol":"XRP_USDT","side":"sell","type":"market","size":"10"}`371372 **`type=limit` — Limit order:**373 - Send `size` + `price`. Truncate `price` to `price_max_precision`, `size` to `quote_increment`.374 - **Note:** If price exceeds `price_max_precision`, the API silently truncates the extra decimals instead of returning an error. Always truncate client-side to ensure the submitted price matches the intended price.375 - Calculate `order_value = size * price`. If `order_value < min_buy_amount` (buy) or `< min_sell_amount` (sell), STOP.376 - If user requested "buy all" / "use full balance": `size = floor(balance / price)` at precision, re-verify minimum.377 - **No hidden risk** — order sits on the book until filled or canceled.378379 **`type=limit_maker` — Post-only (maker-only):**380 - Same params as `limit` (`size` + `price`). Same precision/minimum rules.381 - **CRITICAL behavioral note:** The server **auto-cancels** the order (no error) if the price would immediately match:382 - Buy `limit_maker`: if `price >= best_ask`, order is silently canceled. Price must be **below** best ask.383 - Sell `limit_maker`: if `price <= best_bid`, order is silently canceled. Price must be **above** best bid.384 - Inform user of this risk when setting an aggressive `limit_maker` price.385386 **`type=ioc` — Immediate-or-Cancel:**387 - Same params as `limit` (`size` + `price`). Same precision/minimum rules.388 - **Behavioral note:** Fills whatever quantity is available immediately at the given price; the unfilled remainder is **immediately canceled**. User may receive a partial fill or no fill at all.389390 **2c. Confirm and execute:**391 - Present order summary based on type:392 - market buy: symbol, side=buy, type=market, notional amount393 - market sell: symbol, side=sell, type=market, size (quantity)394 - limit/limit_maker/ioc: symbol, side, type, size, price, estimated order value395 - For `limit_maker`: include a reminder that the order will be auto-canceled if the price crosses the spread.396 - Ask for explicit **"CONFIRM"** before executing. Only proceed after user confirms.397398### Step 3: Verify (WRITE only)399400- After **placing an order**: Call `POST /spot/v4/query/order` with `{"orderId":"..."}` to confirm order status.401- After **canceling an order**: Call `POST /spot/v4/query/open-orders` to verify the order is no longer open.402- Report the verified result to the user.403404---405406## Cross-Skill Workflows407408### Workflow 1: Check Price → Check Balance → Buy4094101. **bitmart-exchange-spot** → `GET /spot/quotation/v3/ticker?symbol=BTC_USDT` — Get current price4112. **bitmart-exchange-spot** → `GET /account/v1/wallet` — Check available balance4123. **bitmart-exchange-spot** → `POST /spot/v2/submit_order` — Place buy order (after user CONFIRM)4134. **bitmart-exchange-spot** → `POST /spot/v4/query/order` — Verify order execution414415---416417## Error Handling418419Spot business error codes are endpoint/version specific. Use the table below for authentication / transport issues and common current spot order-query behavior. For margin borrow / repay / transfer flows, see the margin-only notes after the table.420421| Code | Description | Action |422|------|-------------|--------|423| 1000 | Success | Process response normally |424| 30002 | X-BM-KEY not found | Check that API key is set correctly |425| 30005 | X-BM-SIGN is wrong | Verify signature generation (timestamp, memo, body format) |426| 30006 | X-BM-TIMESTAMP is wrong | Ensure `X-BM-TIMESTAMP` is present and is a Unix timestamp in milliseconds |427| 30007 | Timestamp/recvWindow validation failed | Sync system clock (NTP), send `X-BM-TIMESTAMP` as Unix milliseconds, and ensure `(serverTime - timestamp) <= recvWindow`; `recvWindow` must be Long in `(0,60000]`, default `5000` (max `60000`). For current signed v4 flows, rely on `recvWindow` as the effective request-validity window. |428| 30010 | IP forbidden | Check API key IP whitelist settings |429| 30013 | Rate limit exceeded | Wait for rate limit window to reset, then retry |430| 50005 | Order Id not found / query returned no data | On `POST /spot/v4/query/order`, a missing `orderId` / `clientOrderId` currently returns this code |431| 50021 | param error | For `market` buy, use `notional` (USDT amount) — do NOT use `size`; `size` is silently ignored and causes this error |432| 51011 | param not match : size * price >= X | Read symbol constraints from `GET /spot/v1/symbols/details`; enforce side-specific minimum notional (`min_buy_amount`/`min_sell_amount`) |433| 51012 | below minimum order amount | `notional` (for market buy) or `size * price` (for limit) is below `min_buy_amount`; increase order value to at least the symbol minimum |434| 52000 | Unsupported OrderMode Type | On current v4 query endpoints, use a valid `orderMode` (`spot` / `iso_margin`) or omit the field to query all modes |435| 40044 | Invalid order size | Call `GET /spot/v1/symbols/details`; use symbol precision/increment fields and truncate (not round) `size` and `price` |436| 50023 | Operation is limited | Pair may not support API trading; use a different pair |437| 429 | HTTP rate limit | Back off exponentially, check `X-BM-RateLimit-Reset` header |438| 418 | IP banned | Stop all requests immediately; wait before retrying |439440**Margin-only business codes (do not treat as global spot codes):**441- `51003` — `Account Limit`. Use in margin borrow / repay / transfer context; do **not** use as the generic “order not found” code for v4 order-query flows.442- `51006` — `Exceeds the amount to be repaid`. Use for isolated margin repay flows.443- `51007` — `order_mode not found` in the official business-code table. Do **not** use this as guidance for current v4 query endpoints; invalid `orderMode` requests currently return `52000`.444| 403 | Cloudflare WAF block | Check IP reputation (VPN/cloud IPs are commonly challenged); wait 30-60 seconds and retry; do not auto-retry more than 3 times |445| 503 | Cloudflare challenge / origin unavailable | Same as 403; if response body contains "Cloudflare" or "cf-", it is a Cloudflare interception, not a BitMart error; check network environment |446447### Cloudflare Handling448449BitMart API is behind Cloudflare CDN. If you receive HTTP 403/503 and the response body contains "Cloudflare", "cf-", or an HTML challenge page (instead of JSON):4504511. This is a Cloudflare interception, not a BitMart API error — do not parse as JSON4522. Check if too many requests were sent in a short window (Cloudflare WAF has its own rules independent of API rate limits)4533. Wait 30-60 seconds before retrying4544. If running from a cloud server or VPN, the IP may have low reputation — try from a different network4555. Do not auto-retry more than 3 times — inform the user if the issue persists456457> **Cloudflare 1010:** Non-curl HTTP clients with default bot-like User-Agent strings (e.g., `Python-urllib`, `Go-http-client`) may receive HTTP 403 / error 1010. Always send the `User-Agent: bitmart-skills/spot/v2026.3.23` header from your HTTP library — do not rely on the library default.458459---460461## Security Notes462463- **Never display full API keys or secrets.** Show first 5 + last 4 characters only (e.g., `bmk12...9xyz`).464- **All WRITE operations require explicit user confirmation** before execution. Present a clear summary of the action and wait for "CONFIRM".465- **Recommend IP whitelist** on API keys for additional security.466- **Recommend minimum permissions:** Read-Only + Spot-Trade only (no Withdraw permission).467- **All trading outputs include disclaimer:** "Not financial advice. You are solely responsible for your investment decisions."