BitMart Futures Trading
Overview
53 endpoints total. Table:
| # |
Category |
API Endpoint |
Type |
Description |
| 1 |
Market Data |
GET /contract/public/details |
READ |
Contract specifications |
| 2 |
Market Data |
GET /contract/public/depth |
READ |
Order book |
| 3 |
Market Data |
GET /contract/public/market-trade |
READ |
Recent trades (max 100) |
| 4 |
Market Data |
GET /contract/public/funding-rate |
READ |
Current funding rate |
| 5 |
Market Data |
GET /contract/public/funding-rate-history |
READ |
Historical funding rates |
| 6 |
Market Data |
GET /contract/public/kline |
READ |
K-line (steps: 1,3,5,15,30,60,120,240,360,720,1440,4320,10080) |
| 7 |
Market Data |
GET /contract/public/markprice-kline |
READ |
Mark price K-line |
| 8 |
Market Data |
GET /contract/public/open-interest |
READ |
Open interest |
| 9 |
Market Data |
GET /contract/public/leverage-bracket |
READ |
Leverage tiers / risk limits |
| 10 |
Account |
GET /contract/private/assets-detail |
READ |
Futures account balance |
| 11 |
Account |
GET /contract/private/trade-fee-rate |
READ |
Trade fee rate |
| 12 |
Account |
GET /contract/private/position |
READ |
Current positions |
| 13 |
Account |
GET /contract/private/position-v2 |
READ |
Positions (extended info) |
| 14 |
Account |
GET /contract/private/position-risk |
READ |
Position risk / liquidation |
| 15 |
Account |
GET /contract/private/get-position-mode |
READ |
Current position mode |
| 16 |
Account |
GET /contract/private/transaction-history |
READ |
PnL / funding / fees history |
| 17 |
Trading |
POST /contract/private/submit-order |
WRITE |
Place order |
| 18 |
Trading |
POST /contract/private/cancel-order |
WRITE |
Cancel order |
| 19 |
Trading |
POST /contract/private/cancel-orders |
WRITE |
Batch cancel |
| 20 |
Trading |
POST /contract/private/modify-limit-order |
WRITE |
Amend limit order |
| 21 |
Trading |
POST /contract/private/cancel-all-after |
WRITE |
Timed cancel all |
| 22 |
Trading |
POST /contract/private/submit-leverage |
WRITE |
Set leverage |
| 23 |
Trading |
POST /contract/private/set-position-mode |
WRITE |
Set hedge/one-way mode |
| 24 |
Trading |
POST /account/v1/transfer-contract |
WRITE |
Spot-Futures transfer |
| 25 |
Plan Order |
POST /contract/private/submit-plan-order |
WRITE |
Conditional/trigger order |
| 26 |
Plan Order |
POST /contract/private/cancel-plan-order |
WRITE |
Cancel plan order |
| 27 |
Plan Order |
POST /contract/private/modify-plan-order |
WRITE |
Amend plan order |
| 28 |
TP/SL |
POST /contract/private/submit-tp-sl-order |
WRITE |
Set take-profit/stop-loss |
| 29 |
TP/SL |
POST /contract/private/modify-tp-sl-order |
WRITE |
Modify TP/SL |
| 30 |
TP/SL |
POST /contract/private/modify-preset-plan-order |
WRITE |
Modify preset TP/SL on order |
| 31 |
Trailing |
POST /contract/private/submit-trail-order |
WRITE |
Trailing stop order |
| 32 |
Trailing |
POST /contract/private/cancel-trail-order |
WRITE |
Cancel trailing |
| 33 |
Order Query |
GET /contract/private/order |
READ |
Order by ID |
| 34 |
Order Query |
GET /contract/private/order-history |
READ |
Historical orders |
| 35 |
Order Query |
GET /contract/private/get-open-orders |
READ |
All open orders |
| 36 |
Order Query |
GET /contract/private/current-plan-order |
READ |
Active plan orders |
| 37 |
Order Query |
GET /contract/private/trades |
READ |
Trade / fill history |
| 38 |
Order Query |
POST /account/v1/transfer-contract-list |
READ |
Transfer records |
| 39 |
Sub-Account |
POST /account/contract/sub-account/main/v1/sub-to-main |
WRITE |
Sub → Main transfer (main account) |
| 40 |
Sub-Account |
POST /account/contract/sub-account/main/v1/main-to-sub |
WRITE |
Main → Sub transfer (main account) |
| 41 |
Sub-Account |
POST /account/contract/sub-account/sub/v1/sub-to-main |
WRITE |
Sub → Main transfer (sub account) |
| 42 |
Sub-Account |
GET /account/contract/sub-account/main/v1/wallet |
READ |
Sub-account futures balance |
| 43 |
Sub-Account |
GET /account/contract/sub-account/main/v1/transfer-list |
READ |
Sub-account transfer history |
| 44 |
Sub-Account |
GET /account/contract/sub-account/v1/transfer-history |
READ |
Account transfer history |
| 45 |
Affiliate |
GET /contract/private/affiliate/rebate-list |
READ |
Rebate overview |
| 46 |
Affiliate |
GET /contract/private/affiliate/trade-list |
READ |
Affiliate trade records |
| 47 |
Affiliate |
GET /contract/private/affiliate/rebate-user |
READ |
Single user rebate data |
| 48 |
Affiliate |
GET /contract/private/affiliate/rebate-api |
READ |
Single API user rebate data |
| 49 |
Affiliate |
GET /contract/private/affiliate/invite-check |
READ |
Check if invited user |
| 50 |
Affiliate |
GET /contract/private/affiliate/rebate-inviteUser |
READ |
Invited customer list |
| 51 |
Simulated |
POST /contract/private/claim |
WRITE |
Demo account top-up (demo only) |
| 52 |
System |
GET /system/time |
READ |
Get server time (milliseconds) |
| 53 |
System |
GET /system/service |
READ |
Get system service status / maintenance |
Skill Routing
| User Intent |
Correct Skill |
| Futures/contract trading, leverage, TP/SL, plan orders, trailing stops, sub-account transfers, affiliate/rebate queries, simulated trading |
bitmart-exchange-futures (this skill) |
| Spot buy/sell, order management, spot balance, fee rates |
bitmart-exchange-spot |
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, positions, orders, affiliate (endpoints 10-16, 33-37, 42-50) |
X-BM-KEY |
| SIGNED |
Write operations — trading, leverage, transfers, sub-account transfers, demo claim (endpoints 17-32, 38-41, 51) |
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/futures/v2026.3.23 — SDK source identifier for analytics |
API Base
- Base URL:
https://api-cloud-v2.bitmart.com
- Symbol Format:
BTCUSDT (no separator — unlike spot which uses BTC_USDT)
Key Differences from Spot
| Aspect |
Spot |
Futures |
| Base URL |
api-cloud.bitmart.com |
api-cloud-v2.bitmart.com |
| Symbol Format |
BTC_USDT (underscore) |
BTCUSDT (no separator) |
| Order Side |
"buy" / "sell" (string) |
1 / 2 / 3 / 4 (integer) |
| Leverage |
N/A |
Configurable per symbol |
| Position Mode |
N/A |
hedge_mode / one_way_mode |
| Margin Mode |
N/A |
cross / isolated |
IMPORTANT: Always use the futures base URL (api-cloud-v2) for contract endpoints. Using the spot base URL will fail.
Standard Response Format
Success:
{
"code": 1000,
"message": "OK",
"trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": { ... }
}
Error:
{
"code": 40035,
"message": "Order not exist",
"trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": null
}
Important: code == 1000 means success. Any other code is an error.
GET requests: Parameters go in the query string.
POST requests: Parameters go in the JSON body.
Order Side Reference
| Value |
Hedge Mode |
One-Way Mode |
| 1 |
Open Long (buy_open_long) |
Buy |
| 2 |
Close Short (buy_close_short) |
Buy (Reduce Only) |
| 3 |
Close Long (sell_close_long) |
Sell (Reduce Only) |
| 4 |
Open Short (sell_open_short) |
Sell |
Hedge mode mapping:
- To open long: side = 1
- To close long: side = 3
- To open short: side = 4
- To close short: side = 2
One-way mode: Use side 1 (buy) or 4 (sell). The system infers whether to open or close.
Order Mode Reference
| Value |
Name |
Description |
| 1 |
GTC |
Good Till Cancel — order stays open until filled or canceled |
| 2 |
FOK |
Fill or Kill — must fill entirely or cancel immediately |
| 3 |
IOC |
Immediate or Cancel — fill what's available, cancel the rest |
| 4 |
Maker Only |
Post Only — rejected if it would immediately match |
Rate Limits
| Endpoint |
Rate |
Target |
| Public Market Data (most) |
12/2sec |
IP |
| Open Interest |
2/2sec |
IP |
| Assets Detail |
12/2sec |
KEY |
| Trade Fee Rate |
2/2sec |
KEY |
| Position / Position V2 |
6/2sec |
KEY |
| Position Risk |
24/2sec |
KEY |
| Get Position Mode |
2/2sec |
KEY |
| Transaction History |
6/2sec |
KEY |
| Order Detail |
50/2sec |
KEY |
| Order History / Trades |
6/2sec |
KEY |
| Open Orders / Plan Orders |
50/2sec |
KEY |
| Submit Order |
24/2sec |
KEY |
| Cancel Order |
40/2sec |
KEY |
| Cancel Orders (batch) |
2/2sec |
KEY |
| Modify Order |
24/2sec |
UID |
| Plan / TP-SL / Trail Orders |
24/2sec |
UID |
| Cancel Plan Order |
40/2sec |
UID |
| Cancel All After |
4/2sec |
UID |
| Set Leverage |
24/2sec |
KEY |
| Set Position Mode |
2/2sec |
KEY |
| Transfer |
1/2sec |
KEY |
| Transfer List |
1/2sec |
KEY |
| Sub-Account Transfers (39-41) |
8/2sec |
KEY |
| Sub-Account Wallet (42) |
12/2sec |
KEY |
| Sub-Account History (43-44) |
8/2sec |
KEY |
| Affiliate Endpoints (45-50) |
24/2sec |
KEY |
GET /system/time |
10/sec |
IP |
GET /system/service |
10/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 contract details (no auth)
curl -s -H "User-Agent: bitmart-skills/futures/v2026.3.23" 'https://api-cloud-v2.bitmart.com/contract/public/details?symbol=BTCUSDT'
Example 2: Get futures positions (KEYED)
curl -s -H "X-BM-KEY: $BITMART_API_KEY" \
-H "User-Agent: bitmart-skills/futures/v2026.3.23" \
'https://api-cloud-v2.bitmart.com/contract/private/position?symbol=BTCUSDT'
Example 3: Open long BTC position (SIGNED)
TIMESTAMP=$(date +%s000)
BODY='{"symbol":"BTCUSDT","side":1,"type":"market","size":1,"leverage":"10","open_type":"cross"}'
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-v2.bitmart.com/contract/private/submit-order' \
-H "User-Agent: bitmart-skills/futures/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"
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, positions, balance, order queries, funding rates
- WRITE operations: open/close position, set leverage, place plan order, set TP/SL, trailing stop, transfer
Step 1.5: Pre-Trade Position Check (MANDATORY for open/leverage operations)
Before executing ANY of: open position (POST /contract/private/submit-order with side 1 or 4), set leverage (POST /contract/private/submit-leverage), or change margin mode:
- Call
GET /contract/private/position-v2?symbol=<SYMBOL> to check for existing positions and current margin mode (open_type)
- Evaluate the entire
data[] array returned by position-v2 — do not assume there is only one row
- Parse each row's
current_amount as a number before comparing it. The API returns string values such as "0".
- If any row's parsed
current_amount is non-zero (existing position found):
- You MUST inherit the relevant non-zero position row's
leverage value — do NOT send a different leverage in the order
- You MUST inherit the relevant non-zero position row's
open_type (margin mode: cross or isolated) — do NOT send a different margin mode
- If the user explicitly requested different leverage or margin mode: STOP and warn:
"You have an existing [X]x [cross/isolated] [LONG/SHORT] position of [size] contracts. Changing leverage or margin mode while a position is open is commonly rejected by the API (for example, code 40012/40040). Please close the existing position first if you want to change these settings."
- Do not attempt to change
position_mode while any non-zero position row exists
- Wait for user decision before proceeding
- If every row's parsed
current_amount is 0: proceed with user-specified leverage and margin mode
- If the request becomes mode-sensitive (for example, deciding whether to switch between
hedge_mode and one_way_mode, or explaining current mode-dependent behavior), call GET /contract/private/get-position-mode before making that decision. Do not treat get-position-mode as a hard prerequisite for every plain open-position flow.
Step 1.55: Pre-Mode-Switch Clean-State Check (MANDATORY when changing position mode)
position_mode is an account-wide setting. Before calling POST /contract/private/set-position-mode:
- Ensure Step 1.5 found no existing position (every row's parsed
current_amount is 0)
- Call
GET /contract/private/get-open-orders and verify there are no open orders on the account
- If any open orders or other occupied state remain: STOP and ask the user to clear them before retrying the mode switch
- If
set-position-mode returns 40059, treat that as "account is not in a clean state for mode switching" and stop
Step 1.6: TP/SL Order Parameter Rules (MANDATORY when setting TP/SL on a position)
When the user asks to set take-profit or stop-loss on an existing futures position, use POST /contract/private/submit-tp-sl-order.
CRITICAL — Do NOT confuse these two mechanisms:
preset_take_profit_price / preset_stop_loss_price: optional fields on submit-order to attach TP/SL at position-open time
submit-tp-sl-order: standalone endpoint to set TP/SL on an already-open position — uses trigger_price + executive_price, NOT take_profit_price/stop_loss_price
Required parameters:
| Parameter |
Type |
Value |
Notes |
symbol |
String |
e.g. BTCUSDT |
|
type |
String |
"take_profit" or "stop_loss" |
NEVER "market" or "limit" |
side |
Int |
3 (close long) or 2 (close short) |
Must match position direction |
trigger_price |
String |
Activation price |
Long TP: > entry; Long SL: < entry |
executive_price |
String |
"0" for market fill; or a limit price |
|
price_type |
Int |
1 last price / 2 mark price |
Default: 1 |
plan_category |
Int |
1 TP/SL order / 2 Position TP/SL order (default) |
For existing-position TP/SL, use 2. Omitting the field currently defaults to 2, but sending 2 explicitly is clearer. |
Always submit TP and SL as two separate API calls. One call for take-profit, one for stop-loss.
Long BTC TP example: {"symbol":"BTCUSDT","type":"take_profit","side":3,"trigger_price":"72000","executive_price":"0","price_type":1,"plan_category":2}
Long BTC SL example: {"symbol":"BTCUSDT","type":"stop_loss","side":3,"trigger_price":"64000","executive_price":"0","price_type":1,"plan_category":2}
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 |
create_time, update_time (order responses) |
Milliseconds |
÷ 1000 → Unix seconds → local time |
server_time (system time) |
Milliseconds |
÷ 1000 → Unix seconds → local time |
timestamp (K-line candle open time) |
Seconds |
Direct → Unix seconds → local time |
open_timestamp, funding_time (contract details) |
Milliseconds |
÷ 1000 → Unix seconds → local time |
Query parameter timestamps for futures endpoints (start_time, end_time) are endpoint-specific:
- Seconds:
/contract/public/kline, /contract/public/markprice-kline, /contract/private/order-history, /contract/private/trades, and affiliate rebate endpoints (/contract/private/affiliate/...)
- Milliseconds:
/contract/private/transaction-history
Do NOT assume all futures start_time / end_time are seconds — always follow the target endpoint definition.
Display format: YYYY-MM-DD HH:MM:SS in the user's local timezone. Example: timestamp 1709971200000 (ms) → 2024-03-09 16:00:00 (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 sub-steps below, then ask for "CONFIRM":
2a. submit-order conditional param selection:
| Scenario |
Send |
Do NOT send |
Open position, type=limit (side=1 or 4) |
symbol, side, type:"limit", price, size, leverage, open_type |
— |
Open position, type=market (side=1 or 4) |
symbol, side, type:"market", size, leverage, open_type |
price (ignored, causes confusion) |
Close position, type=limit (side=2 or 3) |
symbol, side, type:"limit", price, size |
leverage, open_type (not needed for close) |
Close position, type=market (side=2 or 3) |
symbol, side, type:"market", size |
price, leverage, open_type |
Additional constraints:
leverage / open_type for open orders: if an existing position is found (Step 1.5), use the relevant non-zero position row's values — do NOT send different ones.
mode=4 (Maker Only): only valid with type=limit. Never combine with type=market.
preset_take_profit_price / preset_stop_loss_price: only valid for opening orders (side=1 or 4). For TP/SL on an already-open position, use submit-tp-sl-order (see Step 1.6).
size is always an integer (number of contracts). Check the minimum contract size via GET /contract/public/details.
2b. Confirm and execute:
Present a summary (symbol, side, type, price if limit, size, leverage, open_type) and ask for explicit "CONFIRM" before executing.
Step 3: Verify (WRITE only)
- After opening a position: Call
GET /contract/private/position-v2 to confirm position was opened. Report entry price, size, leverage, liquidation price, margin used.
- After closing a position: Call
GET /contract/private/position-v2 to confirm position was closed or reduced. Report realized PnL.
- After placing an order: Call
GET /contract/private/order to confirm order status.
- After canceling an order: Call
GET /contract/private/get-open-orders to verify the order is no longer open.
- Report the verified result to the user.
See references/open-position.md, references/close-position.md, references/plan-order.md, and references/tp-sl.md for detailed step-by-step workflows.
References
- API Reference — All 53 endpoints with full parameters, examples, and response fields
- Open Position — Step-by-step open position workflow
- Close Position — Step-by-step close position workflow
- Plan Orders — Conditional/trigger order workflow
- TP/SL — Take-profit/stop-loss workflow
Cross-Skill Workflows
Workflow 1: Transfer Funds → Open Position → Monitor
- bitmart-exchange-futures →
POST /account/v1/transfer-contract — Transfer USDT from spot to futures
- bitmart-exchange-futures →
POST /contract/private/submit-leverage — Set leverage
- bitmart-exchange-futures →
POST /contract/private/submit-order — Open position (after user CONFIRM)
- bitmart-exchange-futures →
GET /contract/private/position-v2 — Monitor position
Workflow 2: Check Spot Balance → Transfer → Open Futures
- bitmart-exchange-spot →
GET /account/v1/wallet — Check spot balance
- bitmart-exchange-futures →
POST /account/v1/transfer-contract — Transfer to futures
- bitmart-exchange-futures →
POST /contract/private/submit-order — Open position
Error Handling
| 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 signed contract flows that expose recvWindow, 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 |
| 40035 |
Order not exist |
Verify the order ID is correct and belongs to this account |
| 40044 |
Invalid order size |
Check min/max limits via GET /contract/public/details |
| 40027 |
Insufficient balance |
Check futures balance; may need to transfer from spot |
| 42000 |
Insufficient balance (margin) |
Reduce order size or add margin |
| 40021 |
Position does not exist |
Verify position is still open before trying to close |
| 40040 |
Invalid leverage / mode constraint |
Check leverage bracket and current position state; if position exists, keep current leverage + open_type |
| 40012 |
Parameter/state conflict |
Commonly appears when leverage/mode conflicts with current position/order state; query GET /contract/private/position-v2 and inherit existing leverage + open_type |
| 429 |
HTTP rate limit |
Back off exponentially, check X-BM-RateLimit-Reset header |
| 418 |
IP banned |
Stop all requests immediately; wait before retrying |
| 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/futures/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 + Futures-Trade only (no Withdraw permission).
- Leverage warning: Higher leverage amplifies both gains and losses. Always inform the user of the liquidation price before opening leveraged positions.
- All trading outputs include disclaimer: "Not financial advice. You are solely responsible for your investment decisions. Futures trading carries significant risk of loss."
Reference: Order Types
| Type |
Description |
limit |
Execute at specified price or better |
market |
Execute immediately at best available price |
Reference: Order Sides
| Value |
Hedge Mode |
One-Way Mode |
| 1 |
Open Long |
Buy |
| 2 |
Close Short |
Buy (Reduce Only) |
| 3 |
Close Long |
Sell (Reduce Only) |
| 4 |
Open Short |
Sell |
Reference: Order Modes
| Value |
Name |
Description |
| 1 |
GTC |
Good Till Cancel |
| 2 |
FOK |
Fill or Kill |
| 3 |
IOC |
Immediate or Cancel |
| 4 |
Maker Only |
Post Only — rejected if it would immediately match |
Reference: Order States
| State |
Code |
Description |
| Approving |
1 |
Order being validated |
| Pending |
2 |
Order accepted, awaiting fill |
| Closed |
4 |
Order completed (filled or canceled) |
Reference: Open Types (Margin Mode)
| Value |
Description |
cross |
Cross margin — all available balance used as margin |
isolated |
Isolated margin — only allocated margin is at risk |
Reference: Position Modes
| Value |
Description |
hedge_mode |
Can hold simultaneous long and short positions |
one_way_mode |
Can hold only one direction at a time |
Reference: Plan Categories
| Value |
Description |
| 1 |
TP/SL order — applies to a specific order quantity |
| 2 |
Position TP/SL — applies to the entire position (default) |
Reference: Price Types
| Value |
Description |
| 1 |
Last price (default) — triggers based on last trade price |
| 2 |
Fair price (mark price) — triggers based on mark price |
Reference: Price Way (Plan Orders)
| Value |
Description |
| 1 |
Bullish — trigger when price rises above trigger_price |
| 2 |
Bearish — trigger when price drops below trigger_price |
Reference: Transfer Types
| Value |
Description |
spot_to_contract |
Spot wallet to futures wallet |
contract_to_spot |
Futures wallet to spot wallet |
Reference: Flow Types (Transaction History)
| Value |
Description |
| 0 |
All types |
| 1 |
Transfer |
| 2 |
Realized PNL |
| 3 |
Funding Fee |
| 4 |
Commission |
| 5 |
Liquidation |
Reference: STP Modes (Self-Trade Prevention)
| Value |
Description |
| 1 |
Cancel Maker (default) |
| 2 |
Cancel Taker |
| 3 |
Cancel Both |
Reference: K-Line Steps
| Step (minutes) |
Description |
| 1 |
1-minute candles |
| 3 |
3-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 |
| 360 |
6-hour candles |
| 720 |
12-hour candles |
| 1440 |
1-day candles |
| 4320 |
3-day candles |
| 10080 |
1-week candles |
1---2name: bitmart-exchange-futures3description: Use when the user asks about BitMart futures or contract trading, including opening/closing positions, setting leverage, placing plan (conditional) orders, take-profit/stop-loss, trailing orders, checking futures positions, managing futures account, sub-account transfers, affiliate/rebate queries, or simulated trading. Do NOT use for spot trading (use bitmart-exchange-spot).4---56# BitMart Futures Trading78## Overview91053 endpoints total. Table:1112| # | Category | API Endpoint | Type | Description |13|---|----------|-------------|------|-------------|14| 1 | Market Data | `GET /contract/public/details` | READ | Contract specifications |15| 2 | Market Data | `GET /contract/public/depth` | READ | Order book |16| 3 | Market Data | `GET /contract/public/market-trade` | READ | Recent trades (max 100) |17| 4 | Market Data | `GET /contract/public/funding-rate` | READ | Current funding rate |18| 5 | Market Data | `GET /contract/public/funding-rate-history` | READ | Historical funding rates |19| 6 | Market Data | `GET /contract/public/kline` | READ | K-line (steps: 1,3,5,15,30,60,120,240,360,720,1440,4320,10080) |20| 7 | Market Data | `GET /contract/public/markprice-kline` | READ | Mark price K-line |21| 8 | Market Data | `GET /contract/public/open-interest` | READ | Open interest |22| 9 | Market Data | `GET /contract/public/leverage-bracket` | READ | Leverage tiers / risk limits |23| 10 | Account | `GET /contract/private/assets-detail` | READ | Futures account balance |24| 11 | Account | `GET /contract/private/trade-fee-rate` | READ | Trade fee rate |25| 12 | Account | `GET /contract/private/position` | READ | Current positions |26| 13 | Account | `GET /contract/private/position-v2` | READ | Positions (extended info) |27| 14 | Account | `GET /contract/private/position-risk` | READ | Position risk / liquidation |28| 15 | Account | `GET /contract/private/get-position-mode` | READ | Current position mode |29| 16 | Account | `GET /contract/private/transaction-history` | READ | PnL / funding / fees history |30| 17 | Trading | `POST /contract/private/submit-order` | WRITE | Place order |31| 18 | Trading | `POST /contract/private/cancel-order` | WRITE | Cancel order |32| 19 | Trading | `POST /contract/private/cancel-orders` | WRITE | Batch cancel |33| 20 | Trading | `POST /contract/private/modify-limit-order` | WRITE | Amend limit order |34| 21 | Trading | `POST /contract/private/cancel-all-after` | WRITE | Timed cancel all |35| 22 | Trading | `POST /contract/private/submit-leverage` | WRITE | Set leverage |36| 23 | Trading | `POST /contract/private/set-position-mode` | WRITE | Set hedge/one-way mode |37| 24 | Trading | `POST /account/v1/transfer-contract` | WRITE | Spot-Futures transfer |38| 25 | Plan Order | `POST /contract/private/submit-plan-order` | WRITE | Conditional/trigger order |39| 26 | Plan Order | `POST /contract/private/cancel-plan-order` | WRITE | Cancel plan order |40| 27 | Plan Order | `POST /contract/private/modify-plan-order` | WRITE | Amend plan order |41| 28 | TP/SL | `POST /contract/private/submit-tp-sl-order` | WRITE | Set take-profit/stop-loss |42| 29 | TP/SL | `POST /contract/private/modify-tp-sl-order` | WRITE | Modify TP/SL |43| 30 | TP/SL | `POST /contract/private/modify-preset-plan-order` | WRITE | Modify preset TP/SL on order |44| 31 | Trailing | `POST /contract/private/submit-trail-order` | WRITE | Trailing stop order |45| 32 | Trailing | `POST /contract/private/cancel-trail-order` | WRITE | Cancel trailing |46| 33 | Order Query | `GET /contract/private/order` | READ | Order by ID |47| 34 | Order Query | `GET /contract/private/order-history` | READ | Historical orders |48| 35 | Order Query | `GET /contract/private/get-open-orders` | READ | All open orders |49| 36 | Order Query | `GET /contract/private/current-plan-order` | READ | Active plan orders |50| 37 | Order Query | `GET /contract/private/trades` | READ | Trade / fill history |51| 38 | Order Query | `POST /account/v1/transfer-contract-list` | READ | Transfer records |52| 39 | Sub-Account | `POST /account/contract/sub-account/main/v1/sub-to-main` | WRITE | Sub → Main transfer (main account) |53| 40 | Sub-Account | `POST /account/contract/sub-account/main/v1/main-to-sub` | WRITE | Main → Sub transfer (main account) |54| 41 | Sub-Account | `POST /account/contract/sub-account/sub/v1/sub-to-main` | WRITE | Sub → Main transfer (sub account) |55| 42 | Sub-Account | `GET /account/contract/sub-account/main/v1/wallet` | READ | Sub-account futures balance |56| 43 | Sub-Account | `GET /account/contract/sub-account/main/v1/transfer-list` | READ | Sub-account transfer history |57| 44 | Sub-Account | `GET /account/contract/sub-account/v1/transfer-history` | READ | Account transfer history |58| 45 | Affiliate | `GET /contract/private/affiliate/rebate-list` | READ | Rebate overview |59| 46 | Affiliate | `GET /contract/private/affiliate/trade-list` | READ | Affiliate trade records |60| 47 | Affiliate | `GET /contract/private/affiliate/rebate-user` | READ | Single user rebate data |61| 48 | Affiliate | `GET /contract/private/affiliate/rebate-api` | READ | Single API user rebate data |62| 49 | Affiliate | `GET /contract/private/affiliate/invite-check` | READ | Check if invited user |63| 50 | Affiliate | `GET /contract/private/affiliate/rebate-inviteUser` | READ | Invited customer list |64| 51 | Simulated | `POST /contract/private/claim` | WRITE | Demo account top-up (demo only) |65| 52 | System | `GET /system/time` | READ | Get server time (milliseconds) |66| 53 | System | `GET /system/service` | READ | Get system service status / maintenance |6768---6970## Skill Routing7172| User Intent | Correct Skill |73|------------|---------------|74| Futures/contract trading, leverage, TP/SL, plan orders, trailing stops, sub-account transfers, affiliate/rebate queries, simulated trading | **bitmart-exchange-futures** (this skill) |75| Spot buy/sell, order management, spot balance, fee rates | bitmart-exchange-spot |7677---7879## Authentication8081### Credential Check (Before Any Private API Call)8283Before calling any authenticated endpoint, verify credentials are available:84851. Check for environment variables:86 - `BITMART_API_KEY` — API key87 - `BITMART_API_SECRET` — Secret key88 - `BITMART_API_MEMO` — Memo string892. Or check for config file: `~/.bitmart/config.toml`90 ```toml91 [default]92 api_key = "your-api-key"93 api_secret = "your-secret-key"94 memo = "your-memo"95 ```963. If missing: **STOP**. Guide user to set up credentials. Do NOT proceed with any authenticated call.9798**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.99100### Auth Levels101102| Level | When | Headers Required |103|-------|------|-----------------|104| **NONE** | Public market data (endpoints 1-9) | None |105| **KEYED** | Read-only private data — balances, positions, orders, affiliate (endpoints 10-16, 33-37, 42-50) | `X-BM-KEY` |106| **SIGNED** | Write operations — trading, leverage, transfers, sub-account transfers, demo claim (endpoints 17-32, 38-41, 51) | `X-BM-KEY` + `X-BM-SIGN` + `X-BM-TIMESTAMP` |107108### Signature Generation109110```111timestamp = current UTC time in milliseconds112message = "{timestamp}#{memo}#{request_body_json}"113signature = HMAC-SHA256(secret_key, message) → hex string114```115116- For **POST** requests: `request_body_json` is the JSON body string.117- For **GET** requests: `request_body_json` is an empty string `""`.118119### Required Headers (SIGNED)120121| Header | Value |122|--------|-------|123| `Content-Type` | `application/json` |124| `X-BM-KEY` | API key |125| `X-BM-SIGN` | Hex-encoded HMAC-SHA256 signature |126| `X-BM-TIMESTAMP` | Current UTC timestamp in milliseconds |127| `User-Agent` | `bitmart-skills/futures/v2026.3.23` — SDK source identifier for analytics |128129---130131## API Base132133- **Base URL**: `https://api-cloud-v2.bitmart.com`134- **Symbol Format**: `BTCUSDT` (no separator — unlike spot which uses `BTC_USDT`)135136## Key Differences from Spot137138| Aspect | Spot | Futures |139|--------|------|---------|140| Base URL | `api-cloud.bitmart.com` | `api-cloud-v2.bitmart.com` |141| Symbol Format | `BTC_USDT` (underscore) | `BTCUSDT` (no separator) |142| Order Side | `"buy"` / `"sell"` (string) | `1` / `2` / `3` / `4` (integer) |143| Leverage | N/A | Configurable per symbol |144| Position Mode | N/A | `hedge_mode` / `one_way_mode` |145| Margin Mode | N/A | `cross` / `isolated` |146147**IMPORTANT:** Always use the futures base URL (`api-cloud-v2`) for contract endpoints. Using the spot base URL will fail.148149## Standard Response Format150151**Success:**152```json153{154 "code": 1000,155 "message": "OK",156 "trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",157 "data": { ... }158}159```160161**Error:**162```json163{164 "code": 40035,165 "message": "Order not exist",166 "trace": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",167 "data": null168}169```170171**Important:** `code == 1000` means success. Any other code is an error.172173**GET requests:** Parameters go in the query string.174**POST requests:** Parameters go in the JSON body.175176---177178## Order Side Reference179180| Value | Hedge Mode | One-Way Mode |181|-------|------------|--------------|182| 1 | Open Long (buy_open_long) | Buy |183| 2 | Close Short (buy_close_short) | Buy (Reduce Only) |184| 3 | Close Long (sell_close_long) | Sell (Reduce Only) |185| 4 | Open Short (sell_open_short) | Sell |186187**Hedge mode mapping:**188- To **open long**: side = 1189- To **close long**: side = 3190- To **open short**: side = 4191- To **close short**: side = 2192193**One-way mode:** Use side 1 (buy) or 4 (sell). The system infers whether to open or close.194195## Order Mode Reference196197| Value | Name | Description |198|-------|------|-------------|199| 1 | GTC | Good Till Cancel — order stays open until filled or canceled |200| 2 | FOK | Fill or Kill — must fill entirely or cancel immediately |201| 3 | IOC | Immediate or Cancel — fill what's available, cancel the rest |202| 4 | Maker Only | Post Only — rejected if it would immediately match |203204---205206## Rate Limits207208| Endpoint | Rate | Target |209|----------|------|--------|210| Public Market Data (most) | 12/2sec | IP |211| Open Interest | 2/2sec | IP |212| Assets Detail | 12/2sec | KEY |213| Trade Fee Rate | 2/2sec | KEY |214| Position / Position V2 | 6/2sec | KEY |215| Position Risk | 24/2sec | KEY |216| Get Position Mode | 2/2sec | KEY |217| Transaction History | 6/2sec | KEY |218| Order Detail | 50/2sec | KEY |219| Order History / Trades | 6/2sec | KEY |220| Open Orders / Plan Orders | 50/2sec | KEY |221| Submit Order | 24/2sec | KEY |222| Cancel Order | 40/2sec | KEY |223| Cancel Orders (batch) | 2/2sec | KEY |224| Modify Order | 24/2sec | UID |225| Plan / TP-SL / Trail Orders | 24/2sec | UID |226| Cancel Plan Order | 40/2sec | UID |227| Cancel All After | 4/2sec | UID |228| Set Leverage | 24/2sec | KEY |229| Set Position Mode | 2/2sec | KEY |230| Transfer | 1/2sec | KEY |231| Transfer List | 1/2sec | KEY |232| Sub-Account Transfers (39-41) | 8/2sec | KEY |233| Sub-Account Wallet (42) | 12/2sec | KEY |234| Sub-Account History (43-44) | 8/2sec | KEY |235| Affiliate Endpoints (45-50) | 24/2sec | KEY |236| `GET /system/time` | 10/sec | IP |237| `GET /system/service` | 10/sec | IP |238239**Rate limit response headers:**240- `X-BM-RateLimit-Remaining` — Number of requests already used in the current window241- `X-BM-RateLimit-Limit` — Maximum allowed requests in the current window242- `X-BM-RateLimit-Reset` — Current time window length (seconds)243244**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.245246If rate limited (HTTP 429), wait for the reset period before retrying.247248---249250## Quickstart251252### Example 1: Get BTC contract details (no auth)253254```bash255curl -s -H "User-Agent: bitmart-skills/futures/v2026.3.23" 'https://api-cloud-v2.bitmart.com/contract/public/details?symbol=BTCUSDT'256```257258### Example 2: Get futures positions (KEYED)259260```bash261curl -s -H "X-BM-KEY: $BITMART_API_KEY" \262 -H "User-Agent: bitmart-skills/futures/v2026.3.23" \263 'https://api-cloud-v2.bitmart.com/contract/private/position?symbol=BTCUSDT'264```265266### Example 3: Open long BTC position (SIGNED)267268```bash269TIMESTAMP=$(date +%s000)270BODY='{"symbol":"BTCUSDT","side":1,"type":"market","size":1,"leverage":"10","open_type":"cross"}'271SIGN=$(echo -n "${TIMESTAMP}#${BITMART_API_MEMO}#${BODY}" | openssl dgst -sha256 -hmac "$BITMART_API_SECRET" | awk '{print $NF}')272curl -s -X POST 'https://api-cloud-v2.bitmart.com/contract/private/submit-order' \273 -H "User-Agent: bitmart-skills/futures/v2026.3.23" \274 -H "Content-Type: application/json" \275 -H "X-BM-KEY: $BITMART_API_KEY" \276 -H "X-BM-SIGN: $SIGN" \277 -H "X-BM-TIMESTAMP: $TIMESTAMP" \278 -d "$BODY"279```280281---282283## Operation Flow284285### Step 0: Credential Check286287Verify `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.288289### Step 1: Identify User Intent290291Parse user request and map to a READ or WRITE operation:292293- **READ** operations: market data, positions, balance, order queries, funding rates294- **WRITE** operations: open/close position, set leverage, place plan order, set TP/SL, trailing stop, transfer295296### Step 1.5: Pre-Trade Position Check (MANDATORY for open/leverage operations)297298Before executing ANY of: open position (`POST /contract/private/submit-order` with side 1 or 4), set leverage (`POST /contract/private/submit-leverage`), or change margin mode:2993001. Call `GET /contract/private/position-v2?symbol=<SYMBOL>` to check for existing positions and current margin mode (`open_type`)3012. Evaluate the entire `data[]` array returned by `position-v2` — do **not** assume there is only one row3023. Parse each row's `current_amount` as a number before comparing it. The API returns string values such as `"0"`.3034. **If any row's parsed `current_amount` is non-zero (existing position found):**304 - **You MUST inherit** the relevant non-zero position row's `leverage` value — do NOT send a different leverage in the order305 - **You MUST inherit** the relevant non-zero position row's `open_type` (margin mode: `cross` or `isolated`) — do NOT send a different margin mode306 - If the user explicitly requested different leverage or margin mode: **STOP** and warn:307 > "You have an existing [X]x [cross/isolated] [LONG/SHORT] position of [size] contracts. Changing leverage or margin mode while a position is open is commonly rejected by the API (for example, code 40012/40040). Please close the existing position first if you want to change these settings."308 - Do **not** attempt to change `position_mode` while any non-zero position row exists309 - Wait for user decision before proceeding3105. **If every row's parsed `current_amount` is 0:** proceed with user-specified leverage and margin mode3116. If the request becomes **mode-sensitive** (for example, deciding whether to switch between `hedge_mode` and `one_way_mode`, or explaining current mode-dependent behavior), call `GET /contract/private/get-position-mode` before making that decision. Do not treat `get-position-mode` as a hard prerequisite for every plain open-position flow.312313### Step 1.55: Pre-Mode-Switch Clean-State Check (MANDATORY when changing position mode)314315`position_mode` is an account-wide setting. Before calling `POST /contract/private/set-position-mode`:3163171. Ensure Step 1.5 found **no** existing position (every row's parsed `current_amount` is `0`)3182. Call `GET /contract/private/get-open-orders` and verify there are **no** open orders on the account3193. If any open orders or other occupied state remain: **STOP** and ask the user to clear them before retrying the mode switch3204. If `set-position-mode` returns `40059`, treat that as "account is not in a clean state for mode switching" and stop321322### Step 1.6: TP/SL Order Parameter Rules (MANDATORY when setting TP/SL on a position)323324When the user asks to set take-profit or stop-loss on an **existing futures position**, use `POST /contract/private/submit-tp-sl-order`.325326**CRITICAL — Do NOT confuse these two mechanisms:**327- `preset_take_profit_price` / `preset_stop_loss_price`: optional fields on `submit-order` to attach TP/SL at position-open time328- `submit-tp-sl-order`: standalone endpoint to set TP/SL on an **already-open position** — uses `trigger_price` + `executive_price`, NOT `take_profit_price`/`stop_loss_price`329330**Required parameters:**331332| Parameter | Type | Value | Notes |333|-----------|------|-------|-------|334| `symbol` | String | e.g. `BTCUSDT` | |335| `type` | String | `"take_profit"` or `"stop_loss"` | NEVER `"market"` or `"limit"` |336| `side` | Int | `3` (close long) or `2` (close short) | Must match position direction |337| `trigger_price` | String | Activation price | Long TP: > entry; Long SL: < entry |338| `executive_price` | String | `"0"` for market fill; or a limit price | |339| `price_type` | Int | `1` last price / `2` mark price | Default: `1` |340| `plan_category` | Int | `1` TP/SL order / `2` Position TP/SL order (default) | For existing-position TP/SL, use `2`. Omitting the field currently defaults to `2`, but sending `2` explicitly is clearer. |341342**Always submit TP and SL as two separate API calls.** One call for take-profit, one for stop-loss.343344Long BTC TP example: `{"symbol":"BTCUSDT","type":"take_profit","side":3,"trigger_price":"72000","executive_price":"0","price_type":1,"plan_category":2}`345Long BTC SL example: `{"symbol":"BTCUSDT","type":"stop_loss","side":3,"trigger_price":"64000","executive_price":"0","price_type":1,"plan_category":2}`346347### Timestamp Display Rules348349API responses contain Unix timestamps in different units. When displaying any timestamp to the user, **always convert to human-readable local time**.350351| Field | Unit | Conversion |352|-------|------|------------|353| `create_time`, `update_time` (order responses) | Milliseconds | `÷ 1000` → Unix seconds → local time |354| `server_time` (system time) | Milliseconds | `÷ 1000` → Unix seconds → local time |355| `timestamp` (K-line candle open time) | Seconds | Direct → Unix seconds → local time |356| `open_timestamp`, `funding_time` (contract details) | Milliseconds | `÷ 1000` → Unix seconds → local time |357358**Query parameter timestamps** for futures endpoints (`start_time`, `end_time`) are **endpoint-specific**:359360- **Seconds**: `/contract/public/kline`, `/contract/public/markprice-kline`, `/contract/private/order-history`, `/contract/private/trades`, and affiliate rebate endpoints (`/contract/private/affiliate/...`)361- **Milliseconds**: `/contract/private/transaction-history`362363Do NOT assume all futures `start_time` / `end_time` are seconds — always follow the target endpoint definition.364365**Display format:** `YYYY-MM-DD HH:MM:SS` in the user's local timezone. Example: timestamp `1709971200000` (ms) → `2024-03-09 16:00:00` (UTC+8).366367**Common mistakes to avoid:**368- Do NOT treat millisecond timestamps as seconds (produces dates in year 55000+)369- Do NOT display raw numeric timestamps — always convert to readable format370- Do NOT assume UTC — convert to the user's local timezone371372### Step 2: Execute373374- **READ**: Call the API endpoint, parse response, format data for user display.375- **WRITE**: Follow sub-steps below, then ask for **"CONFIRM"**:376377 **2a. submit-order conditional param selection:**378379 | Scenario | Send | Do NOT send |380 |----------|------|-------------|381 | Open position, `type=limit` (side=1 or 4) | `symbol`, `side`, `type:"limit"`, `price`, `size`, `leverage`, `open_type` | — |382 | Open position, `type=market` (side=1 or 4) | `symbol`, `side`, `type:"market"`, `size`, `leverage`, `open_type` | `price` (ignored, causes confusion) |383 | Close position, `type=limit` (side=2 or 3) | `symbol`, `side`, `type:"limit"`, `price`, `size` | `leverage`, `open_type` (not needed for close) |384 | Close position, `type=market` (side=2 or 3) | `symbol`, `side`, `type:"market"`, `size` | `price`, `leverage`, `open_type` |385386 Additional constraints:387 - **`leverage` / `open_type` for open orders**: if an existing position is found (Step 1.5), use the relevant non-zero position row's values — do NOT send different ones.388 - **`mode=4` (Maker Only)**: only valid with `type=limit`. Never combine with `type=market`.389 - **`preset_take_profit_price` / `preset_stop_loss_price`**: only valid for opening orders (side=1 or 4). For TP/SL on an **already-open** position, use `submit-tp-sl-order` (see Step 1.6).390 - **`size` is always an integer** (number of contracts). Check the minimum contract size via `GET /contract/public/details`.391392 **2b. Confirm and execute:**393 Present a summary (symbol, side, type, price if limit, size, leverage, open_type) and ask for explicit **"CONFIRM"** before executing.394395### Step 3: Verify (WRITE only)396397- After **opening a position**: Call `GET /contract/private/position-v2` to confirm position was opened. Report entry price, size, leverage, liquidation price, margin used.398- After **closing a position**: Call `GET /contract/private/position-v2` to confirm position was closed or reduced. Report realized PnL.399- After **placing an order**: Call `GET /contract/private/order` to confirm order status.400- After **canceling an order**: Call `GET /contract/private/get-open-orders` to verify the order is no longer open.401- Report the verified result to the user.402403See `references/open-position.md`, `references/close-position.md`, `references/plan-order.md`, and `references/tp-sl.md` for detailed step-by-step workflows.404405---406407## References408409- **[API Reference](references/api-reference.md)** — All 53 endpoints with full parameters, examples, and response fields410- **[Open Position](references/open-position.md)** — Step-by-step open position workflow411- **[Close Position](references/close-position.md)** — Step-by-step close position workflow412- **[Plan Orders](references/plan-order.md)** — Conditional/trigger order workflow413- **[TP/SL](references/tp-sl.md)** — Take-profit/stop-loss workflow414415---416417## Cross-Skill Workflows418419### Workflow 1: Transfer Funds → Open Position → Monitor4204211. **bitmart-exchange-futures** → `POST /account/v1/transfer-contract` — Transfer USDT from spot to futures4222. **bitmart-exchange-futures** → `POST /contract/private/submit-leverage` — Set leverage4233. **bitmart-exchange-futures** → `POST /contract/private/submit-order` — Open position (after user CONFIRM)4244. **bitmart-exchange-futures** → `GET /contract/private/position-v2` — Monitor position425426### Workflow 2: Check Spot Balance → Transfer → Open Futures4274281. **bitmart-exchange-spot** → `GET /account/v1/wallet` — Check spot balance4292. **bitmart-exchange-futures** → `POST /account/v1/transfer-contract` — Transfer to futures4303. **bitmart-exchange-futures** → `POST /contract/private/submit-order` — Open position431432---433434## Error Handling435436| Code | Description | Action |437|------|-------------|--------|438| 1000 | Success | Process response normally |439| 30002 | X-BM-KEY not found | Check that API key is set correctly |440| 30005 | X-BM-SIGN is wrong | Verify signature generation (timestamp, memo, body format) |441| 30006 | X-BM-TIMESTAMP is wrong | Ensure `X-BM-TIMESTAMP` is present and is a Unix timestamp in milliseconds |442| 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 signed contract flows that expose `recvWindow`, rely on `recvWindow` as the effective request-validity window. |443| 30010 | IP forbidden | Check API key IP whitelist settings |444| 30013 | Rate limit exceeded | Wait for rate limit window to reset, then retry |445| 40035 | Order not exist | Verify the order ID is correct and belongs to this account |446| 40044 | Invalid order size | Check min/max limits via `GET /contract/public/details` |447| 40027 | Insufficient balance | Check futures balance; may need to transfer from spot |448| 42000 | Insufficient balance (margin) | Reduce order size or add margin |449| 40021 | Position does not exist | Verify position is still open before trying to close |450| 40040 | Invalid leverage / mode constraint | Check leverage bracket and current position state; if position exists, keep current leverage + `open_type` |451| 40012 | Parameter/state conflict | Commonly appears when leverage/mode conflicts with current position/order state; query `GET /contract/private/position-v2` and inherit existing leverage + `open_type` |452| 429 | HTTP rate limit | Back off exponentially, check `X-BM-RateLimit-Reset` header |453| 418 | IP banned | Stop all requests immediately; wait before retrying |454| 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 |455| 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 |456457### Cloudflare Handling458459BitMart 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):4604611. This is a Cloudflare interception, not a BitMart API error — do not parse as JSON4622. Check if too many requests were sent in a short window (Cloudflare WAF has its own rules independent of API rate limits)4633. Wait 30-60 seconds before retrying4644. If running from a cloud server or VPN, the IP may have low reputation — try from a different network4655. Do not auto-retry more than 3 times — inform the user if the issue persists466467> **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/futures/v2026.3.23` header from your HTTP library — do not rely on the library default.468469---470471## Security Notes472473- **Never display full API keys or secrets.** Show first 5 + last 4 characters only (e.g., `bmk12...9xyz`).474- **All WRITE operations require explicit user confirmation** before execution. Present a clear summary of the action and wait for "CONFIRM".475- **Recommend IP whitelist** on API keys for additional security.476- **Recommend minimum permissions:** Read-Only + Futures-Trade only (no Withdraw permission).477- **Leverage warning:** Higher leverage amplifies both gains and losses. Always inform the user of the liquidation price before opening leveraged positions.478- **All trading outputs include disclaimer:** "Not financial advice. You are solely responsible for your investment decisions. Futures trading carries significant risk of loss."479480---481482## Reference: Order Types483484| Type | Description |485|------|-------------|486| `limit` | Execute at specified price or better |487| `market` | Execute immediately at best available price |488489## Reference: Order Sides490491| Value | Hedge Mode | One-Way Mode |492|-------|------------|--------------|493| 1 | Open Long | Buy |494| 2 | Close Short | Buy (Reduce Only) |495| 3 | Close Long | Sell (Reduce Only) |496| 4 | Open Short | Sell |497498## Reference: Order Modes499500| Value | Name | Description |501|-------|------|-------------|502| 1 | GTC | Good Till Cancel |503| 2 | FOK | Fill or Kill |504| 3 | IOC | Immediate or Cancel |505| 4 | Maker Only | Post Only — rejected if it would immediately match |506507## Reference: Order States508509| State | Code | Description |510|-------|------|-------------|511| Approving | 1 | Order being validated |512| Pending | 2 | Order accepted, awaiting fill |513| Closed | 4 | Order completed (filled or canceled) |514515## Reference: Open Types (Margin Mode)516517| Value | Description |518|-------|-------------|519| `cross` | Cross margin — all available balance used as margin |520| `isolated` | Isolated margin — only allocated margin is at risk |521522## Reference: Position Modes523524| Value | Description |525|-------|-------------|526| `hedge_mode` | Can hold simultaneous long and short positions |527| `one_way_mode` | Can hold only one direction at a time |528529## Reference: Plan Categories530531| Value | Description |532|-------|-------------|533| 1 | TP/SL order — applies to a specific order quantity |534| 2 | Position TP/SL — applies to the entire position (default) |535536## Reference: Price Types537538| Value | Description |539|-------|-------------|540| 1 | Last price (default) — triggers based on last trade price |541| 2 | Fair price (mark price) — triggers based on mark price |542543## Reference: Price Way (Plan Orders)544545| Value | Description |546|-------|-------------|547| 1 | Bullish — trigger when price rises above trigger_price |548| 2 | Bearish — trigger when price drops below trigger_price |549550## Reference: Transfer Types551552| Value | Description |553|-------|-------------|554| `spot_to_contract` | Spot wallet to futures wallet |555| `contract_to_spot` | Futures wallet to spot wallet |556557## Reference: Flow Types (Transaction History)558559| Value | Description |560|-------|-------------|561| 0 | All types |562| 1 | Transfer |563| 2 | Realized PNL |564| 3 | Funding Fee |565| 4 | Commission |566| 5 | Liquidation |567568## Reference: STP Modes (Self-Trade Prevention)569570| Value | Description |571|-------|-------------|572| 1 | Cancel Maker (default) |573| 2 | Cancel Taker |574| 3 | Cancel Both |575576## Reference: K-Line Steps577578| Step (minutes) | Description |579|----------------|-------------|580| 1 | 1-minute candles |581| 3 | 3-minute candles |582| 5 | 5-minute candles |583| 15 | 15-minute candles |584| 30 | 30-minute candles |585| 60 | 1-hour candles |586| 120 | 2-hour candles |587| 240 | 4-hour candles |588| 360 | 6-hour candles |589| 720 | 12-hour candles |590| 1440 | 1-day candles |591| 4320 | 3-day candles |592| 10080 | 1-week candles |