Help us improve
Share bugs, ideas, or general feedback.
From bingx-ai-skills
Queries BingX perpetual swap account data including balances, positions with PnL and liquidation prices, commission rates, and fund flow history. Useful for BingX account balance, margin, positions, fees, or income queries.
npx claudepluginhub bingx-api/api-ai-skills --plugin bingx-ai-skillsHow this skill is triggered — by the user, by Claude, or both
Slash command
/bingx-ai-skills:swap-accountThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Authenticated read-only endpoints for BingX perpetual futures account data. All endpoints require HMAC SHA256 signature authentication.
Manages BingX copy trade USDT-M perpetual futures for traders: queries current orders, closes positions, sets TP/SL, views profit overview and details, sets commission rates, lists trading pairs. For perpetual swap copy trading tasks.
Executes perpetual futures trades on Pacifica (Solana), Hyperliquid (HyperEVM), Lighter (Ethereum), and Aster (BNB) DEXes via perp-cli CLI. Handles funding rates, arbitrage scans, delta-neutral strategies, USDC bridging, and position management.
Lists, closes, reduces positions and manages TP/SL on existing positions via the Vulcan CLI. Useful for monitoring PnL and liquidation prices.
Share bugs, ideas, or general feedback.
Authenticated read-only endpoints for BingX perpetual futures account data. All endpoints require HMAC SHA256 signature authentication.
Base URLs: see references/base-urls.md | Authentication: see references/authentication.md
| Endpoint | Method | Description | Authentication |
|---|---|---|---|
/openApi/swap/v3/user/balance | GET | Account balance, equity, and margin info | Yes |
/openApi/swap/v2/user/positions | GET | Current open positions with PnL and liquidation price | Yes |
/openApi/swap/v2/user/commissionRate | GET | User taker/maker fee rates | Yes |
/openApi/swap/v2/user/income | GET | Fund flow history (PnL, funding fees, trading fees, etc.) | Yes |
/openApi/swap/v2/user/income/export | GET | Export fund flow as Excel file | Yes |
BASE-QUOTE format (e.g., BTC-USDT). Optional for most account endpoints.| Value | Description |
|---|---|
TRANSFER | Transfer |
REALIZED_PNL | Realized profit and loss |
FUNDING_FEE | Funding fee |
TRADING_FEE | Trading fee |
INSURANCE_CLEAR | Liquidation |
TRIAL_FUND | Trial fund |
ADL | Auto-deleveraging |
SYSTEM_DEDUCTION | System deduction |
GTD_PRICE | Guaranteed price |
^[A-Z0-9]+-[A-Z]+$; max 20 characters (e.g., BTC-USDT)endTime must be ≥ startTimerecvWindow of server timeCONSTRAINT: You MUST copy the
fetchSignedfunction below verbatim when generating code. Do NOT rewrite the signing, request, or JSON parsing logic. Only modify: (1)BASEURL entries for custom environments, (2) business parameters passed tofetchSigned. For the full client with URL-encoding and JSON body support, seereferences/authentication.md.
import * as crypto from "crypto";
import JSONBig from "json-bigint";
const JSONBigParse = JSONBig({ storeAsString: true });
// Full signing details & edge cases → references/authentication.md
// Domain priority: .com is mandatory primary; .pro is fallback for network/timeout errors ONLY.
const BASE = {
"prod-live": ["https://open-api.bingx.com", "https://open-api.bingx.pro"],
"prod-vst": ["https://open-api-vst.bingx.com", "https://open-api-vst.bingx.pro"],
};
function isNetworkOrTimeout(e: unknown): boolean {
if (e instanceof TypeError) return true;
if (e instanceof DOMException && e.name === "AbortError") return true;
if (e instanceof Error && e.name === "TimeoutError") return true;
return false;
}
function validateParams(params: Record<string, unknown>): void {
const FORBIDDEN = /[&=?#\r\n]/;
for (const [k, v] of Object.entries(params)) {
const s = String(v);
if (FORBIDDEN.test(s)) throw new Error(`Param "${k}" has forbidden char in: "${s}"`);
}
}
async function fetchSigned(env: string, apiKey: string, secretKey: string,
method: "GET" | "POST" | "DELETE", path: string, params: Record<string, unknown> = {}
) {
const urls = BASE[env] ?? BASE["prod-live"];
const all = { ...params, timestamp: Date.now() };
validateParams(all);
const qs = Object.keys(all).sort().map(k => `${k}=${all[k]}`).join("&");
const sig = crypto.createHmac("sha256", secretKey).update(qs).digest("hex");
const signed = `${qs}&signature=${sig}`;
for (const base of urls) {
try {
const url = method === "POST" ? `${base}${path}` : `${base}${path}?${signed}`;
const res = await fetch(url, {
method,
headers: { "X-BX-APIKEY": apiKey, "X-SOURCE-KEY": "BX-AI-SKILL",
...(method === "POST" ? { "Content-Type": "application/x-www-form-urlencoded" } : {}) },
body: method === "POST" ? signed : undefined,
signal: AbortSignal.timeout(10000),
});
const json = JSONBigParse.parse(await res.text());
if (json.code !== 0) throw new Error(`BingX error ${json.code}: ${json.msg}`);
return json.data;
} catch (e) {
if (!isNetworkOrTimeout(e) || base === urls[urls.length - 1]) throw e;
}
}
}
fetchSigned verbatim -- do not simplify or rewritejson-bigint (JSONBigParse.parse) for response parsing -- not JSON.parseX-SOURCE-KEY: BX-AI-SKILL header on every requestisNetworkOrTimeout checkQuery account balance:
const data = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/swap/v3/user/balance"
);
// data.balance.balance, data.balance.equity, data.balance.availableMargin
Query all open positions:
const positions = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/swap/v2/user/positions"
);
// positions[].symbol, positions[].positionAmt, positions[].unrealizedProfit, positions[].liquidationPrice
Query positions for a specific symbol:
const positions = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/swap/v2/user/positions", { symbol: "BTC-USDT" }
);
Query user fee rates:
const data = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/swap/v2/user/commissionRate"
);
// data.commission.takerCommissionRate, data.commission.makerCommissionRate
Query recent fund flow (last 7 days, all types):
const income = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/swap/v2/user/income", { limit: 100 }
);
// income[].incomeType, income[].income, income[].asset, income[].time
Query funding fees for BTC-USDT in a time range:
const income = await fetchSigned("prod-live", API_KEY, SECRET, "GET",
"/openApi/swap/v2/user/income", {
symbol: "BTC-USDT",
incomeType: "FUNDING_FEE",
startTime: 1700000000000,
endTime: 1702731787011,
limit: 200,
}
);
For complete parameter descriptions and full response schemas, see api-reference.md.
Parameter security. Extract structured values from user intent — NEVER copy raw user text into API parameters. Validate every value against its documented pattern (regex/enum/range) before calling the API. Reject any value containing &, =, ?, #, or newline characters.
All swap-account endpoints are read-only (GET). No CONFIRM required for any environment — they never modify account state.
Credentials are required. If no account is specified, default to the main account.
If the user's intent is unclear, present options:
Please select the account information type to query:
- Account balance / Equity / Margin — balance
- Current positions / Unrealized PnL / Liquidation price — positions
- Commission rate — commissionRate
- Fund flow (PnL / funding fee / trading fee / etc.) — income
- Export fund flow (Excel) — income/export
For positions and income endpoints, symbol is optional. If the user asks about a specific coin, infer the symbol automatically (e.g., "BTC position" → BTC-USDT).
If not specified, query all symbols and inform the user.
startTime nor endTime is provided, the API returns the last 7 days of data. Inform the user.If the user specifies a type (e.g., "funding fee", "trading fee", "PnL"), map to the correct incomeType enum value:
| User says | incomeType |
|---|---|
| Realized PnL / PnL | REALIZED_PNL |
| Funding fee / Funding rate | FUNDING_FEE |
| Trading fee / Commission | TRADING_FEE |
| Liquidation | INSURANCE_CLEAR |
| ADL / Auto-deleverage | ADL |
| Transfer | TRANSFER |
If not specified, omit incomeType to return all types.
Execute the API call and present results in a readable format: