Skip to main content
Glama
trustxai

amazing-binance-mcp

by trustxai

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
BINANCE_API_KEYYesThe API key (X-MBX-APIKEY). Required for account/trading tools.
BINANCE_API_URLNoREST base URL. Overrides the testnet switch when set.
BINANCE_TESTNETNo'1' routes /api/v3 to the spot testnet. Use testnet keys.
BINANCE_API_SECRETNoHMAC secret of a 'System generated' key.
BINANCE_ALLOW_TRADINGNoKill-switch. '1' allows orders, cancels, order lists, transfers, convert, TWAP and dust conversion. Never withdrawals.
BINANCE_RECV_WINDOW_MSNoSigned-request validity window in ms (max 60000).
BINANCE_PRIVATE_KEY_PATHNoPath to the Ed25519 (or RSA) private-key PEM of a 'Self-generated' key. Takes precedence over the HMAC secret.
BINANCE_PRIVATE_KEY_PASSPHRASENoPassphrase of an encrypted PEM.
BINANCE_REQUEST_TIMEOUT_SECONDSNoPer-request HTTP timeout.

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
binance_get_convert_pairsA

List the convertible asset pairs and their per-pair minimum/maximum amounts.

Calls GET /sapi/v1/convert/exchangeInfounauthenticated (no key needed) but IP weight 3000 of a 12,000/min budget, so four unfiltered calls exhaust a minute. The pair list barely changes: cache the answer and pass from_asset/to_asset to keep the response small.

When to Use:

  • Before quoting, to check a pair is convertible at all and that the amount you plan to convert sits between fromAssetMinAmount and fromAssetMaxAmount.

  • To find what a given asset can be converted into (from_asset="BTC").

When NOT to Use:

  • To get a price — that is binance_get_convert_quote (a quote reserves a ratio).

  • To read spot symbol filters — that is binance_get_exchange_info; convert pairs and spot trading pairs are different lists with different rules.

Returns: One row per pair: from → to plus the min/max amount on both legs. Markdown display is capped at 100 pairs with a note to narrow the filter; response_format="json" carries every row returned.

Examples: params = {"from_asset": "BTC"} params = {"from_asset": "BTC", "to_asset": "USDT"}

Error Handling: 429 means the IP weight budget is gone — wait out Retry-After rather than retrying; this single endpoint is 3000 weight per call.

binance_get_convert_asset_infoA

Show the decimal precision (fraction) Convert accepts for each asset.

Calls GET /sapi/v1/convert/assetInfo (SIGNED, IP weight 100). fraction is the number of decimal places an amount may carry for that asset on the convert rail — sending more precision than this is what -1111 rejects.

When to Use:

  • Before binance_get_convert_quote, to round from_amount/to_amount correctly.

  • When a quote was rejected for precision.

When NOT to Use:

  • To find which pairs exist or their min/max sizes — that is binance_get_convert_pairs.

Returns: One row per asset: asset and its accepted decimal places, filtered client-side when asset is given. Markdown display is capped at 100 rows.

Examples: params = {} params = {"asset": "BTC"}

Error Handling: -2015 means the key lacks permission or this machine's IP is not on the key's allowlist; the spot testnet has no /sapi endpoints at all (404).

binance_get_convert_quoteA

Request a convert quote: a reserved ratio, valid for 10 s to 2 minutes.

Calls POST /sapi/v1/convert/getQuote (SIGNED, UID weight 200). This moves no funds — it is on the client's POST-read allowlist, so it works with the trading kill-switch off — but it is not free either: a quote is a short-lived reservation, so do not poll it in a loop.

Nothing is converted until the quote is accepted with binance_accept_convert_quote before validTimestamp. After that instant the quoteId is void and a new quote is needed.

When to Use:

  • To price a conversion (what you would receive, and at what ratio) before deciding.

  • As the first half of every conversion: quote → human approves → accept.

When NOT to Use:

  • For an indicative market price — binance_get_ticker_price is free and does not reserve anything.

  • To convert at a price that is not currently available — place a convert limit order with binance_place_convert_limit_order instead.

Returns: The quoteId, the ratio and inverseRatio, both amounts, and the expiry instant (validTimestamp) rendered as UTC, plus the instruction to accept it before it expires.

Examples: params = {"from_asset": "BTC", "to_asset": "USDT", "from_amount": "0.01"} params = {"from_asset": "USDT", "to_asset": "BTC", "to_amount": "0.5", "valid_time": "1m"}

Error Handling: -1111 means the amount carries more decimals than the asset's fraction (see binance_get_convert_asset_info); a rejection about limits means the amount is outside the pair's min/max (see binance_get_convert_pairs); -2015 means the key lacks permission or the IP is not allowlisted.

binance_accept_convert_quoteA

Accept a convert quote and EXECUTE the conversion. This moves real funds.

Calls POST /sapi/v1/convert/acceptQuote (SIGNED, UID weight 500). The conversion is irreversible: converting back needs a new quote at whatever ratio the market offers then, so the round trip costs the spread twice.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1. The gate lives in the HTTP client, so no tool can bypass it. If you see that error, the operator has deliberately put the server in read-only mode — report it, do not try to work around it.

Always price the conversion with binance_get_convert_quote first (it works even with the kill-switch off) and have the human approve that exact quoteId and amount.

When to Use:

  • Immediately after a human approved the ratio in a fresh quote, before it expires.

When NOT to Use:

  • To "see what would happen" — that is binance_get_convert_quote.

  • To convert at a price that is not on offer now — use binance_place_convert_limit_order.

Returns: A confirmation echoing exactly what Binance returned — orderId, createTime and orderStatus verbatim (PROCESS / ACCEPT_SUCCESS / SUCCESS / FAIL). Only SUCCESS means the assets were exchanged; the other statuses are reported as-is with the next step, never paraphrased as "converted".

Examples: params = {"quote_id": "12415572564"}

Error Handling: An expired or already-used quoteId is rejected by Binance — request a new quote rather than retrying this one. A 5xx or a timeout means the execution status is UNKNOWN: check with binance_get_convert_order_status (by quote_id) before accepting anything again — never blind-retry a conversion.

binance_get_convert_order_statusA

Check one conversion's status by orderId or by the quoteId it came from.

Calls GET /sapi/v1/convert/orderStatus (SIGNED, UID weight 100). Exactly one of order_id / quote_id — Binance rejects both together.

When to Use:

  • After binance_accept_convert_quote returned PROCESS or ACCEPT_SUCCESS, to find out whether it settled.

  • After a timeout or 5xx on an acceptance, to learn whether the conversion happened before retrying anything.

When NOT to Use:

  • For a list of past conversions — use binance_get_convert_history.

  • For resting limit orders — use binance_get_convert_open_limit_orders.

Returns: The conversion's assets, amounts, ratio, status and creation time, with the status echoed verbatim.

Examples: params = {"order_id": "933256278426274426"} params = {"quote_id": "12415572564"}

Error Handling: -2015 means the key lacks permission or the IP is not allowlisted; an unknown id is rejected by Binance rather than returning an empty result.

binance_get_convert_historyA

List past conversions, either for one <=30-day window or across a walked range.

Calls GET /sapi/v1/convert/tradeFlow (SIGNED, UID weight 3000 per call of a 180,000/min budget — 60 calls a minute at most, and the default budget here spends 72,000 of it).

Binance requires both startTime and endTime and caps the span at 30 days, and the endpoint has no cursor/offset/page parameter of any kind. The only continuation it offers is the moreData flag: when it is true, the same window is re-asked with endTime = min(createTime) (inclusive — an exclusive - 1 would drop rows tied on that instant but cut off by limit; the re-read duplicates are deduped by orderId) until it comes back false. Both modes below automate that.

  • Single window (default): start_time / end_time. Give one and the other is filled locally by the 30-day rule; give neither and the last 30 days are used.

  • Walk: since (plus optional until / resume_before) slices the range into <=29-day windows, newest-first, until since is reached or max_calls runs out.

The two sets are mutually exclusive — mixing them is rejected locally.

When to Use:

  • To reconcile conversions for a period, or to find the orderId of a past conversion.

  • To pull more than 30 days of history without hand-rolling the windowing (walk mode).

When NOT to Use:

  • To check one conversion you just made — binance_get_convert_order_status is UID 100 against this endpoint's 3000.

  • For resting limit orders, which are not conversions yet — binance_get_convert_open_limit_orders.

Returns: Conversions newest-first (time, from → to amounts, ratio, status, orderId), deduped by orderId within the call, the number of API calls spent, and — when the walk stopped early — a resume_before cursor marking the boundary of the next unfetched range. A failure mid-walk returns the rows collected so far plus that cursor and the error, never the error alone. Markdown display caps at 50 rows; response_format="json" carries every fetched row.

Pagination/Windows: start_time/end_time/since/until/resume_before all accept epoch ms, a

=12-digit epoch-ms string, or ISO-8601. A single-window span over 30 days is rejected here with a clear message rather than sent on to become a Binance error. limit is <= 1000 (the endpoint's own max). resume_before is always the endTime the next request would have used, so resuming never leaves a gap; overlapping rows are deduped.

Examples: params = {} # the last 30 days, one window params = {"start_time": "2026-08-01", "end_time": "2026-08-20"} params = {"since": "2026-01-01", "max_calls": 12} params = {"since": "2026-01-01", "resume_before": 1756000000000}

Error Handling: -1127 means the span exceeded Binance's cap (this tool validates first, so it should not appear); 429 on /sapi means the UID weight budget is gone — lower max_calls and wait; -2015 means the key lacks permission or the IP is not allowlisted.

binance_place_convert_limit_orderA

Place a convert LIMIT order: convert automatically if the ratio is reached.

Calls POST /sapi/v1/convert/limit/placeOrder (SIGNED, UID weight 500). The order rests until limit_price is reached or expired_type (1_D / 3_D / 7_D / 30_D) expires it. When it triggers it spends real funds, without asking again.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1. The gate lives in the HTTP client, so no tool can bypass it.

Check the pair's limits with binance_get_convert_pairs and the amount precision with binance_get_convert_asset_info first; there is no dry-run for this endpoint.

When to Use:

  • To convert at a ratio the market is not offering right now, after a human approved that price and size.

When NOT to Use:

  • To convert at the current ratio — quote it with binance_get_convert_quote and accept it, which is immediate and shows you the exact ratio first.

  • For a spot LIMIT order on a trading pair — that is binance_place_order, a different book with different fees.

Returns: A confirmation echoing exactly what Binance returned — orderId and status verbatim. A resting order is not a conversion: nothing has been exchanged until it triggers, and this confirmation never says otherwise.

Examples: params = {"base_asset": "BTC", "quote_asset": "USDT", "limit_price": "50000", "side": "BUY", "expired_type": "7_D", "quote_amount": "500"}

Error Handling: A rejection about limits means the amount is outside the pair's min/max (binance_get_convert_pairs); -1111 means too many decimals for the asset (binance_get_convert_asset_info); a 5xx or timeout means the order's status is UNKNOWN — check binance_get_convert_open_limit_orders before placing it again.

binance_cancel_convert_limit_orderA

Cancel a resting convert limit order.

Calls POST /sapi/v1/convert/limit/cancelOrder (SIGNED, UID weight 200).

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1 — cancellation is a signed non-GET like any other state change, so the same gate applies.

When to Use:

  • To pull a convert limit order that no longer reflects the plan, before it triggers.

When NOT to Use:

  • For a spot order — that is binance_cancel_order.

  • To undo a completed conversion: there is no such thing. Converting back needs a new quote at the current ratio.

Returns: A confirmation echoing exactly what Binance returned — orderId and status verbatim.

Examples: params = {"order_id": "1603680255057330400"}

Error Handling: An already-filled, already-cancelled or unknown orderId is rejected by Binance — check binance_get_convert_open_limit_orders for what is actually resting. A 5xx or a timeout means the cancellation status is UNKNOWN: check binance_get_convert_open_limit_orders before cancelling again, because the order may already be gone.

binance_get_convert_open_limit_ordersA

List the convert limit orders currently resting on the account.

Calls GET /sapi/v1/convert/limit/queryOpenOrders (SIGNED, UID weight 3000 of a 180,000/min budget) — cross-asset, no filters, so poll it sparingly.

When to Use:

  • To see what convert limit orders are live, with their expiry instants.

  • Before placing another one, to avoid stacking duplicates.

  • After a timeout on a placement, to learn whether the order actually rested.

When NOT to Use:

  • For completed conversions — binance_get_convert_history.

  • For spot open orders — binance_get_open_orders.

Returns: One row per resting order: creation time, from → to amounts, ratio, status, orderId and the expiry instant. Markdown display caps at 50 rows.

Examples: params = {}

Error Handling: -2015 means the key lacks permission or the IP is not allowlisted; 429 on /sapi means the UID budget is gone — this endpoint alone is 3000 per call.

binance_get_fiat_ordersA

List fiat-rail deposit or withdraw orders (bank transfer/card top-up of the fiat wallet).

Calls GET /sapi/v1/fiat/orders, signed. This is the UID-weighted 45000 fiat-rail ledger — of the 180000/min UID budget that is at most 4 calls per minute. Do not poll this tool in a loop; for a bulk backfill use binance_get_fiat_history, which already budgets calls.

When to Use:

  • Seeing fiat bank-rail deposits into, or withdrawals out of, the fiat wallet (bank transfer, SEPA, card-funded top-ups of the fiat balance — not Spot).

  • Reconciling a specific order by scanning a narrow begin_time/end_time window.

When NOT to Use:

  • Buying/selling crypto with fiat (a card or bank purchase of BTC/ETH/...) — use binance_get_fiat_payments.

  • A long backfill across many pages or months — use binance_get_fiat_history.

  • Binance Card spend — there is no API for that (see the module docstring).

Returns: A markdown list (or JSON with response_format="json") of orders: order number, fiat currency, indicated vs settled amount, fee, method, status, created/updated time. Status values Binance returns: Processing, Failed, Successful, Finished, Refunding, Refunded, Refund Failed, Order Partial credit Stopped.

Pagination: page (1-indexed) / rows (max 500) map directly to the API; the response also reports Binance's own total row count across all pages. Markdown display is capped at 50 rows (with a note naming the next page to request); JSON keeps the full page.

Examples: params = {"transaction_type": "deposit", "rows": 50} params = {"transaction_type": "withdraw", "begin_time": "2026-01-01", "end_time": "2026-02-01"}

Error Handling: A 200 body with success: false is raised by the client as BinanceEnvelopeError and surfaced here as Error: ...; an undocumented span cap on this endpoint typically surfaces as -1127 — narrow begin_time/end_time and retry. A malformed begin_time/end_time returns Error: <field> must be epoch milliseconds or an ISO-8601 string without calling the API.

binance_get_fiat_paymentsA

List crypto buy/sell payments made with fiat (bank transfer or bank-issued card).

Calls GET /sapi/v1/fiat/payments, signed, IP weight 1 (cheap — unlike fiat/orders). A "Credit Card" paymentMethod here is a bank-issued card buying crypto, and is NOT the Binance Card — Binance Card spend has no API surface at all (.memory/research/03-card-and-gaps.md §1); the closest proxies are binance_get_funding_wallet and binance_get_pay_transactions (walletType 4/6).

When to Use:

  • Seeing crypto bought or sold with fiat: source/obtained amounts, price, fee, payment method (buy only), status.

  • Reconciling a specific purchase by scanning a narrow begin_time/end_time window.

When NOT to Use:

  • Bank deposits/withdrawals of fiat itself — use binance_get_fiat_orders.

  • A long backfill across many pages or months — use binance_get_fiat_history.

Returns: A markdown list (or JSON with response_format="json") of payments: order number, fiat amount/currency, obtained crypto amount/currency, price, fee, payment method (buy only), status, created/updated time. Status values Binance returns: Processing, Failed, Successful, Finished, Refunding, Refunded, Refund Failed, Order Partial credit Stopped.

Pagination: page (1-indexed) / rows (max 500) map directly to the API; the response also reports Binance's own total row count across all pages. Markdown display is capped at 50 rows (with a note naming the next page to request); JSON keeps the full page.

Examples: params = {"transaction_type": "buy", "rows": 50} params = {"transaction_type": "sell", "begin_time": "2026-01-01", "end_time": "2026-02-01"}

Error Handling: A 200 body with success: false is raised by the client as BinanceEnvelopeError and surfaced here as Error: .... A malformed begin_time/end_time returns Error: <field> must be epoch milliseconds or an ISO-8601 string without calling the API.

binance_get_fiat_historyA

Walk fiat deposit/withdraw or buy/sell history across pages and time windows.

Tries ONE call spanning beginTime=since .. endTime=now (or resume_before when resuming) and pages page until a short page signals the end. If that wide-span attempt fails with a plausibly span-related HTTP error (commonly -1127, an undocumented span cap on these two endpoints), falls back to walking 30-day windows newest-first instead.

Honors a max_calls budget so one invocation can never blow past the weight-limited call rate — deposits/withdrawals cost UID 45000/call (default budget 4, i.e. the whole 180000/min UID budget for a minute), buys/sells cost IP 1/call (default budget 20). Every request checks the budget first, and a request that itself errors still counts against it, since it still spent real quota.

The walk NEVER discards rows it already has: whenever it stops early — budget exhaustion or ANY request failure, span-related or not — it renders the normal report (rows collected so far, totals, call count) plus a resume_before cursor, and for a failure it also shows the underlying error (via handle_api_error) as a prominent line. Binance treats endTime as inclusive, so a re-fetched boundary row is expected; rows are deduped by orderNo before being returned. The cursor comes in two flavours, worded differently so one is never mistaken for the other: a redo cursor (the wide span, or the window in progress, was not fully covered — page order inside it is undocumented, so the whole thing must be retried) says it "re-covers the same range, it does not advance"; an advance cursor (every window up to it is fully covered; only the budget stopped a NEW window from starting) says rows "were not fetched" before it and to "continue" from there.

Status values Binance returns for fiat orders/payments: Processing, Failed, Successful, Finished, Refunding, Refunded, Refund Failed, Order Partial credit Stopped.

When to Use:

  • A bulk backfill of fiat activity (deposits, withdrawals, or crypto buys/sells with fiat) since account creation, paged and budgeted automatically.

  • Continuing a previous walk that stopped early: pass its resume_before back in.

When NOT to Use:

  • A single narrow lookup — use binance_get_fiat_orders / binance_get_fiat_payments directly with your own begin_time/end_time; it is one call instead of many.

  • Binance Card spend — not retrievable via any API (see the module docstring); a "Credit Card" paymentMethod in buys/sells is a bank card, not the Binance Card.

Returns: Deduped rows sorted newest-first (display capped at 50, JSON keeps the full walked set), a per-fiat-currency total (and, for buys/sells, a per-crypto-currency received total), how many API calls were spent, whether the window fallback triggered, and — when the walk stopped early — a resume_before cursor plus (for a failure) the error that caused the stop.

Examples: params = {"kind": "deposits"} params = {"kind": "buys", "since": "2023-01-01"} params = {"kind": "withdrawals", "resume_before": 1700000000000}

Error Handling: A span-related HTTP error on the wide-span attempt triggers the 30-day-window fallback automatically. Any failure after that point — inside a window, or an auth/rate-limit/envelope/other error that was never span-related — stops the walk instead of raising: the response still shows the rows already collected, the API-call count, a resume_before cursor, and the failure itself via handle_api_error. A malformed since/resume_before returns Error: <field> must be epoch milliseconds or an ISO-8601 string before any call is made.

binance_health_checkA

Verify connectivity, clock drift, and API-key permissions against Binance.

Calls GET /api/v3/ping and GET /api/v3/time (public), then — when credentials are configured — GET /sapi/v1/account/apiRestrictions (signed) to report what the key is allowed to do. Also states whether the trading kill-switch (BINANCE_ALLOW_TRADING) is on.

When to Use:

  • As the first call after configuring the server, to confirm the key signs correctly.

  • To debug -1021 (clock drift), -1022 (signature), or -2015 (permissions / IP) errors.

When NOT to Use:

  • To read balances (use the spot/wallet account tools).

Returns: A markdown block with connectivity, server time vs local drift, the key's permission flags (withdrawals should be OFF, IP restriction ON), and the kill-switch state — or an Error ... string describing the failure.

Error Handling: -2015 means the key's IP allowlist excludes this machine or the key lacks Reading; -1022 means the secret / key type is wrong; on the spot testnet the /sapi call is skipped because the testnet has no wallet endpoints.

binance_get_exchange_infoA

Look up trading rules, symbol status, and order filters for spot symbols.

Calls GET /api/v3/exchangeInfo (weight 20). Without symbol/symbols/permissions/ symbol_status this returns Binance's full symbol universe (3707+ symbols); the response is always capped at 50 symbols here — pass symbol/symbols to narrow it.

When to Use:

  • Before placing an order, to read the LOT_SIZE/PRICE_FILTER/NOTIONAL/MARKET_LOT_SIZE filter values a quantity/price must respect (see binance_place_order).

  • To check whether a symbol is currently TRADING, HALTed, or in BREAK.

  • To discover which symbols share a base/quote asset (with permissions/symbol_status).

When NOT to Use:

  • For live prices — use binance_get_ticker_price or binance_get_avg_price.

  • For account-specific trading permissions — use binance_get_spot_account.

Returns: Markdown: one block per symbol (status, base/quote, order types, filter values), capped at 50 symbols with a note if more matched. JSON: the same data, count vs shown.

Examples: params = {"symbol": "BTCUSDT"} params = {"symbols": ["BTCUSDT", "ETHUSDT"]} params = {"permissions": ["SPOT"], "symbol_status": "TRADING"}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol; combining symbol/symbols with permissions/symbol_status is rejected locally before the call is made.

binance_get_order_bookA

Fetch the current order book (bids/asks) for a symbol.

Calls GET /api/v3/depth. Weight tiers by limit: 1-100 → 5, 101-500 → 25 (this tool's cap is 500; Binance itself allows up to 5000 at weight 250, unavailable here).

When to Use:

  • To see live liquidity/spread before sizing an order.

  • To validate a limit price against the current best bid/ask.

When NOT to Use:

  • For the last traded price only — use binance_get_book_ticker (cheaper, weight 2/4).

  • For historical trades — use binance_get_recent_trades / binance_get_agg_trades.

Returns: Markdown: top 50 levels per side as price/qty tables, with the book's lastUpdateId. JSON: the full requested depth (up to limit), uncapped.

Examples: params = {"symbol": "BTCUSDT", "limit": 20}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol.

binance_get_recent_tradesA

Fetch the most recent public trades for a symbol.

Calls GET /api/v3/trades (weight 25). Always returns the latest trades — there is no way to page backward here (use binance_get_agg_trades with from_id for that).

When to Use:

  • To see the last executed prices/sizes and maker/taker mix for a symbol.

When NOT to Use:

  • To page through trade history by id — use binance_get_agg_trades.

  • For your OWN trades — use binance_get_my_trades (signed).

Returns: Markdown: a table of up to 100 trades (id, time, price, qty, side). JSON: the full requested page (up to limit), uncapped.

Examples: params = {"symbol": "BTCUSDT", "limit": 50}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol.

binance_get_agg_tradesA

Fetch compressed/aggregate trades (same price, same taker order, same timestamp merged).

Calls GET /api/v3/aggTrades (weight 4). Filter with from_id for a stable cursor walk, or start_time/end_time for a time window — Binance rejects a start/end window wider than 1 hour on this endpoint; slice a longer range into ≤ 1h calls.

When to Use:

  • To page through historical trades by id (from_id), which binance_get_recent_trades cannot do.

  • To reconstruct a short time window of trade flow cheaply (weight 4 vs 25).

When NOT to Use:

  • For the very latest trades with no filter — binance_get_recent_trades is simpler.

Returns: Markdown: a table of up to 100 aggregate trades (id, time, price, qty, first/last trade ids, side). JSON: the full requested page (up to limit), uncapped.

Windows: start_time/end_time together must not span more than 1 hour (per Binance's own docs); omit both, or use from_id, for a wider walk.

Examples: params = {"symbol": "BTCUSDT", "from_id": 123456} params = {"symbol": "BTCUSDT", "start_time": "2024-01-01T00:00:00Z", "end_time": "2024-01-01T00:45:00Z"}

Error Handling: A window wider than 1 hour raises Binance -1127 More than 1 hours between startTime and endTime; combining from_id with the time window is rejected locally.

binance_get_klinesA

Fetch OHLCV candlestick data for a symbol.

Calls GET /api/v3/klines (weight 2).

When to Use:

  • For price history / technical analysis over a chosen interval and window.

When NOT to Use:

  • For presentation-smoothed candles matching Binance's own chart UI — use binance_get_ui_klines instead.

  • For the single latest price — use binance_get_ticker_price.

Returns: Markdown: a table of up to 100 candles (open time, OHLC, volume, close time). JSON: the raw array-of-arrays Binance returns (up to limit), uncapped.

Pagination: Walk forward with start_time set to the previous page's last close time + 1ms; start_time/end_time are always interpreted in UTC even when time_zone is set.

Examples: params = {"symbol": "BTCUSDT", "interval": "1h", "limit": 200}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol; an invalid interval is rejected locally by the KlineInterval enum.

binance_get_ui_klinesA

Fetch presentation-adjusted candlestick data, matching Binance's own chart UI.

Calls GET /api/v3/uiKlines (weight 2). Same array shape and parameters as binance_get_klines; Binance smooths/adjusts these for display purposes.

When to Use:

  • When the numbers need to match what a user sees on binance.com/binance app charts.

When NOT to Use:

  • For raw exchange candles used in calculations — use binance_get_klines.

Returns: Same shape as binance_get_klines: markdown table (capped at 100 rows) or JSON.

Examples: params = {"symbol": "BTCUSDT", "interval": "1h", "limit": 200}

Error Handling: Same as binance_get_klines.

binance_get_avg_priceA

Fetch the current average price over Binance's configured window (typically 5 min).

Calls GET /api/v3/avgPrice (weight 2).

When to Use:

  • As a smoothed reference price, e.g. for MARKET order sanity checks.

When NOT to Use:

  • For the latest tick price — use binance_get_ticker_price.

Returns: Markdown: the price, the averaging window in minutes, and the close time. JSON: the raw {mins, price, closeTime} object.

Examples: params = {"symbol": "BTCUSDT"}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol.

binance_get_ticker_24hA

Fetch 24-hour rolling price change statistics.

Calls GET /api/v3/ticker/24hr. Weight: symbol → 2; symbols → 2 for 1-20, 40 for 21-100, 80 for 101+; no symbol at all (all 3700+ symbols) → weight 80 — use sparingly.

When to Use:

  • For a market snapshot: price change %, high/low, volume over the last 24h.

When NOT to Use:

  • For a fixed calendar-day window — use binance_get_trading_day_ticker.

  • For a custom rolling window — use binance_get_rolling_ticker.

Returns: Markdown: up to 50 symbols as stat blocks. JSON: count/shown plus the tickers.

Examples: params = {"symbol": "BTCUSDT"} params = {"symbols": ["BTCUSDT", "ETHUSDT"], "type": "MINI"}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol.

binance_get_ticker_priceA

Fetch the latest price for one, several, or all symbols.

Calls GET /api/v3/ticker/price. Weight: symbol → 2; omitted or symbols → 4 (fetching ALL prices is a flat weight-4 call — cheap even for the whole market).

When to Use:

  • For the current tick price with the least overhead of any ticker endpoint.

When NOT to Use:

  • For bid/ask spread — use binance_get_book_ticker.

  • For 24h stats (change %, volume) — use binance_get_ticker_24h.

Returns: Markdown: a symbol/price table, capped at 100 rows. JSON: count/shown plus prices.

Examples: params = {"symbol": "BTCUSDT"} params = {"symbols": ["BTCUSDT", "ETHUSDT"]}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol.

binance_get_book_tickerA

Fetch the best bid/ask price and quantity for one, several, or all symbols.

Calls GET /api/v3/ticker/bookTicker. Weight: symbol → 2; omitted or symbols → 4.

When to Use:

  • For the current spread and top-of-book size without the full depth of binance_get_order_book.

When NOT to Use:

  • For multiple price levels — use binance_get_order_book.

Returns: Markdown: a table of bid/ask price+qty per symbol, capped at 100 rows. JSON: count/shown plus the tickers.

Examples: params = {"symbol": "BTCUSDT"}

Error Handling: An unknown symbol raises Binance -1121 Invalid symbol.

binance_get_rolling_tickerA

Fetch price change statistics over an arbitrary rolling window.

Calls GET /api/v3/ticker (weight 4 per symbol, capped at 200 once >50 symbols requested). Unlike binance_get_ticker_24h, the window is not fixed at 24 hours.

When to Use:

  • For a custom window (e.g. 4h, 7d) that the fixed 24h/trading-day tickers don't cover.

When NOT to Use:

  • For the standard 24h window — binance_get_ticker_24h is cheaper for that case.

Returns: Markdown: stat blocks per symbol (up to 50 shown). JSON: count/shown plus tickers.

Examples: params = {"symbol": "BTCUSDT", "window_size": "4h"} params = {"symbols": ["BTCUSDT", "ETHUSDT"], "window_size": "7d"}

Error Handling: window_size outside 1m-59m/1h-23h/1d-7d is rejected by Binance; more than 100 symbols or neither symbol nor symbols is rejected locally.

binance_get_trading_day_tickerA

Fetch price change statistics for the current trading day (a fixed calendar window).

Calls GET /api/v3/ticker/tradingDay (weight 4 per symbol, capped at 200 once >50 symbols requested; max 100 symbols per request).

When to Use:

  • For "today's" stats aligned to a specific timezone's midnight — e.g. time_zone="+08:00".

When NOT to Use:

  • For a rolling 24h window instead of a calendar day — use binance_get_ticker_24h.

Returns: Markdown: stat blocks per symbol (up to 50 shown). JSON: count/shown plus tickers.

Examples: params = {"symbol": "BTCUSDT", "time_zone": "+08:00"}

Error Handling: More than 100 symbols or neither symbol nor symbols is rejected locally.

binance_place_oco_orderA

Place a REAL one-cancels-the-other pair (take-profit + stop). This spends real money.

Calls POST /api/v3/orderList/oco (SIGNED, IP weight 1, unfilled-order count 2). Both legs carry the same quantity and the same side; when one triggers, Binance cancels the other. This is the bracket around a position you already hold (SELL) or the breakout/dip pair for one you want (BUY).

Kill-switch. This call is refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1. The gate lives in the HTTP client, so no tool can bypass it. If you see that error, the operator has deliberately put the server in read-only mode — report it, do not try to work around it.

There is no dry-run for a list. binance_test_order validates ONE order, not a list; run it per leg if you want Binance's filter check before committing.

Leg rules, enforced locally before anything is signed:

  • exactly one take-profit leg (LIMIT_MAKER / TAKE_PROFIT / TAKE_PROFIT_LIMIT) and one stop leg (STOP_LOSS / STOP_LOSS_LIMIT);

  • on a SELL the take-profit leg is the above one, on a BUY it is the below one;

  • the above leg's price must be strictly greater than the below leg's. Binance's full rule is above > last traded price > below, and this server does not know the last traded price — only the relationship between the two prices you pass is checked here. Read the market with binance_get_ticker_price first.

When to Use:

  • Bracketing an open position with a target and a stop in one atomic request.

  • Any time two orders must be mutually exclusive — placing them separately risks both filling.

When NOT to Use:

  • For a single order — binance_place_order (spot_orders.py).

  • When the bracket should only arm after an entry fills — that is binance_place_otoco_order.

  • To change an existing list: cancel it with binance_cancel_order_list and place a new one; there is no amend for lists.

Returns: A confirmation echoing exactly what Binance returned: orderListId, contingencyType, listStatusType, listOrderStatus, listClientOrderId, and a ### Legs table built from orderReports when the response carries one (ids only otherwise, and it says so). Nothing is inferred.

Examples: params = {"symbol": "BTCUSDT", "side": "SELL", "quantity": "0.001", "above_type": "LIMIT_MAKER", "above_price": "72000.00", "below_type": "STOP_LOSS_LIMIT", "below_price": "58000.00", "below_stop_price": "58500.00", "below_time_in_force": "GTC", "list_client_order_id": "btc-bracket-001"} params = {"symbol": "BTCUSDT", "side": "BUY", "quantity": "0.001", "above_type": "STOP_LOSS_LIMIT", "above_price": "71000.00", "above_stop_price": "70500.00", "above_time_in_force": "GTC", "below_type": "LIMIT_MAKER", "below_price": "60000.00"}

Error Handling:

  • Error: … trading is disabled … → the kill-switch is off; nothing was sent.

  • -2010 → insufficient balance, a symbol filter (LOT_SIZE / PRICE_FILTER / NOTIONAL), or the pair sits on the wrong side of the last traded price.

  • -2021 means a LIMIT_MAKER leg would have taken liquidity immediately.

  • -1013 / -1111 are precision / filter errors — read binance_get_exchange_info.

  • A 5xx or a timeout means the execution status is UNKNOWN — the list may well be live. Query it with binance_get_order_list (by list_client_order_id if you set one) before doing anything else. NEVER resend blindly.

binance_place_oto_orderA

Place a REAL one-triggers-the-other pair (entry, then follow-up). Real money.

Calls POST /api/v3/orderList/oto (SIGNED, IP weight 1, unfilled-order count 2). The working leg (LIMIT or LIMIT_MAKER) goes on the book immediately. The pending leg is only placed once the working leg is fully filled — until then it sits in PENDING_NEW and does nothing. Cancelling either leg kills the whole list.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1.

There is no dry-run for a list; binance_test_order validates one order at a time.

Mandatory extras, enforced locally (S2 L3419):

  • working_type=LIMITworking_time_in_force;

  • pending_type=LIMITpending_price, pending_time_in_force;

  • pending_type=STOP_LOSS|TAKE_PROFITpending_stop_price and/or pending_trailing_delta;

  • pending_type=STOP_LOSS_LIMIT|TAKE_PROFIT_LIMITpending_price, pending_time_in_force, and pending_stop_price and/or pending_trailing_delta;

  • pending_type=LIMIT_MAKERpending_price. A MARKET pending leg is allowed, but only by pending_quantity — Binance does not support quoteOrderQty inside a list, and this server never sends it.

When to Use:

  • Entry plus a single exit: buy at a limit, and the moment it fills, arm one stop.

  • Chaining two orders where the second must not exist until the first is done.

When NOT to Use:

  • When the follow-up should be a target AND a stop — use binance_place_otoco_order.

  • When both orders should be live at once — that is binance_place_oco_order.

Returns: A confirmation echoing orderListId, contingencyType, listStatusType, listOrderStatus, listClientOrderId and a ### Legs table. A pending leg reported as PENDING_NEW is NOT on the book yet; the table shows exactly what Binance said and nothing more.

Examples: params = {"symbol": "BTCUSDT", "working_type": "LIMIT", "working_side": "BUY", "working_price": "60000.00", "working_quantity": "0.001", "working_time_in_force": "GTC", "pending_type": "LIMIT", "pending_side": "SELL", "pending_quantity": "0.001", "pending_price": "66000.00", "pending_time_in_force": "GTC", "list_client_order_id": "entry-then-target-001"} params = {"symbol": "BTCUSDT", "working_type": "LIMIT_MAKER", "working_side": "BUY", "working_price": "60000.00", "working_quantity": "0.001", "pending_type": "STOP_LOSS", "pending_side": "SELL", "pending_quantity": "0.001", "pending_stop_price": "57000.00"}

Error Handling:

  • Error: … trading is disabled … → the kill-switch is off; nothing was sent.

  • -2010 / -1013 / -1111 are balance, filter and precision failures on either leg.

  • -2021 means the working LIMIT_MAKER would have taken liquidity immediately.

  • A 5xx or a timeout means the execution status is UNKNOWN — query with binance_get_order_list before retrying; a duplicate entry is real money.

binance_place_otoco_orderA

Place a REAL entry that arms a take-profit/stop pair when it fills. Real money.

Calls POST /api/v3/orderList/otoco (SIGNED, IP weight 1, unfilled-order count 3). The working leg (LIMIT or LIMIT_MAKER) rests on the book; once it is fully filled, the two pending legs go on as an OCO pair, so the first of them to trigger cancels the other. Cancelling any leg kills the whole list.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1.

There is no dry-run for a list; binance_test_order validates one order at a time.

Enforced locally before anything is signed (S2 L3571-L3579):

  • working_type=LIMITworking_time_in_force;

  • per pending leg — LIMIT_MAKER → price; STOP_LOSS / TAKE_PROFIT → stop price and/or trailing delta; STOP_LOSS_LIMIT / TAKE_PROFIT_LIMIT → price, time-in-force, and stop price and/or trailing delta;

  • when both pending legs are given, the OCO pairing and the price ordering (pending_above price > pending_below price). The last traded price is unknown to this server, so only the relationship between the prices you pass is checked; Binance applies the full above > last traded price > below rule at trigger time.

Binance marks pending_below_type optional; a list without it is really an OTO, so pass both pending legs unless you mean to place an OTO.

When to Use:

  • The full bracket in one request: entry, target and stop, with nothing armed until the entry fills.

When NOT to Use:

  • When you already hold the position — the bracket alone is binance_place_oco_order.

  • For entry plus a single follow-up — binance_place_oto_order.

Returns: A confirmation echoing orderListId, contingencyType, listStatusType, listOrderStatus, listClientOrderId and a ### Legs table of all three legs exactly as Binance reported them (the pending pair shows as PENDING_NEW until the working leg fills).

Examples: params = {"symbol": "BTCUSDT", "working_type": "LIMIT", "working_side": "BUY", "working_price": "60000.00", "working_quantity": "0.001", "working_time_in_force": "GTC", "pending_side": "SELL", "pending_quantity": "0.001", "pending_above_type": "LIMIT_MAKER", "pending_above_price": "66000.00", "pending_below_type": "STOP_LOSS_LIMIT", "pending_below_price": "57000.00", "pending_below_stop_price": "57500.00", "pending_below_time_in_force": "GTC", "list_client_order_id": "full-bracket-001"}

Error Handling:

  • Error: … trading is disabled … → the kill-switch is off; nothing was sent.

  • -2010 / -1013 / -1111 are balance, filter and precision failures on any leg.

  • -2021 means a LIMIT_MAKER leg would have taken liquidity immediately.

  • A 5xx or a timeout means the execution status is UNKNOWN — query with binance_get_order_list before retrying.

binance_get_order_listA

Look up one order list — OCO, OTO or OTOCO — by id.

Calls GET /api/v3/orderList (SIGNED, IP weight 4). No symbol is needed: pass exactly one id, order_list_id (Binance's numeric orderListId) or orig_client_order_id (the listClientOrderId used when placing). Both at once is rejected locally — Binance resolves the numeric id first and then rejects a mismatch, so the ambiguous call buys nothing.

When to Use:

  • After a 5xx or a timeout on a placement — this is how you find out whether the list exists before considering a retry.

  • To check whether a bracket is still working, or which leg ended it.

When NOT to Use:

  • To see every working list — binance_get_open_order_lists (weight 6).

  • For history across a period — binance_get_all_order_lists.

  • For an individual leg's fills — binance_get_order / binance_get_my_trades with the leg's orderId.

Returns: orderListId, contingencyType, listStatusType, listOrderStatus, listClientOrderId, symbol, transactionTime and the ### Legs table. This endpoint returns orders[] only (ids, no per-leg status), and the answer says so rather than implying more. response_format="json" returns the raw payload.

Examples: params = {"order_list_id": 27} params = {"orig_client_order_id": "btc-bracket-001"}

Error Handling: -2011/-2013 mean no such order list for this account. -1102 means neither id reached Binance. -2015 means the key lacks permission or this IP is not allowlisted.

binance_cancel_order_listA

Cancel an ENTIRE order list — every leg of it — by id.

Calls DELETE /api/v3/orderList (SIGNED, IP weight 1). Pass the symbol plus exactly one id: order_list_id or list_client_order_id. Both at once is rejected locally.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1.

Cancelling is idempotent in effect: a second cancel of the same list returns -2011 ("unknown order") and changes nothing. What it cannot undo is a fill — a leg that has already triggered is gone, and its sibling with it. Note that cancelling ONE leg (via binance_cancel_order) also cancels the whole list; this tool just makes the intent explicit.

When to Use:

  • Pulling a bracket that is no longer wanted, before replacing it.

  • Cleaning up after a partial fill changed the position the bracket was sized for.

When NOT to Use:

  • To cancel everything on a symbol, lists included — binance_cancel_all_open_orders (spot_orders.py) does it in one call.

  • To see what would be cancelled — binance_get_order_list first; that read is free of consequence and this one is not.

Returns: A confirmation echoing the cancelled list: orderListId, contingencyType, listStatusType, listOrderStatus and the ### Legs table from orderReports[] with each leg's status (CANCELED) and its original client id.

Examples: params = {"symbol": "BTCUSDT", "order_list_id": 27} params = {"symbol": "BTCUSDT", "list_client_order_id": "btc-bracket-001", "new_client_order_id": "cancel-bracket-001"}

Error Handling: -2011 means the list is not cancellable: it does not exist, already completed, or was already cancelled. A 5xx/timeout leaves the cancel UNKNOWN: check with binance_get_order_list before assuming either way — do not assume the legs are gone.

binance_get_all_order_listsA

List this account's order lists — working, completed and cancelled — across symbols.

Calls GET /api/v3/allOrderList (SIGNED, IP weight 20). There is no symbol filter: the endpoint is account-wide. Narrow it with from_id (lists with orderListId >= it) or a start_time/end_time window — Binance forbids combining them, and that is rejected locally. The window may not exceed 24 hours, also checked here so you get a clear message instead of Binance's -1127.

When to Use:

  • Reconstructing which brackets existed during a given day.

  • Paging list history forward with a from_id cursor.

When NOT to Use:

  • For what is armed right now — binance_get_open_order_lists costs weight 6.

  • For one known list — binance_get_order_list costs weight 4.

  • For plain (non-list) orders — binance_get_all_orders (spot_orders.py).

Returns: A markdown table (time, symbol, orderListId, contingencyType, listStatusType, listOrderStatus, listClientOrderId, leg count) capped at 50 rows, or the raw array with response_format="json".

Pagination: limit is 1-1000 (Binance default 500) and at most 50 rows are rendered; use response_format="json" or narrow the window for the rest. from_id pages forward: pass the last orderListId you saw, plus one.

Windows: start_time/end_time accept epoch ms or ISO-8601 and must span 24 h or less together. Omit everything to get the most recent limit lists.

Examples: params = {"limit": 10} params = {"start_time": "2026-09-22T00:00:00Z", "end_time": "2026-09-22T23:59:59Z"} params = {"from_id": 27}

Error Handling: A window wider than 24 h, and from_id combined with a time bound, are both rejected locally. -1127 from Binance means a too-wide window reached it anyway; -1128 is an invalid parameter combination. -2015 means the key lacks permission or this IP is not allowlisted.

binance_get_open_order_listsA

List the order lists that are still working, across every symbol.

Calls GET /api/v3/openOrderList (SIGNED, IP weight 6). The endpoint takes no filters — it is account-wide by construction, which is exactly what makes it the right first read before placing another bracket.

When to Use:

  • Before placing a new bracket, to see what is already armed on the same position.

  • After a 5xx/timeout on a placement, when you have no id to query.

When NOT to Use:

  • For one known list — binance_get_order_list (weight 4).

  • For lists that already finished — binance_get_all_order_lists.

  • For plain open orders — binance_get_open_orders (spot_orders.py); a list's legs also appear there individually.

Returns: A markdown table (time, symbol, orderListId, contingencyType, listStatusType, listOrderStatus, listClientOrderId, leg count) capped at 50 rows, or the raw array with response_format="json".

Examples: params = {} params = {"response_format": "json"}

Error Handling: -2015 means the key lacks permission or this IP is not allowlisted. An empty list is a valid answer: no bracket is armed.

binance_get_pay_transactionsA

Fetch Binance Pay transactions (merchant payments, C2C, refunds, payouts) for the account.

Calls GET /sapi/v1/pay/transactions (UID weight 3000). Binance Card spending is NOT available via API — this only shows Binance Pay activity; a payment funded by the Binance Card appears here with walletType 4 or 6 ("card"), which is the closest visibility this server has into card usage.

When to Use:

  • To review recent (<= 90 day) Binance Pay activity: merchant payments, C2C transfers, refunds, crypto box, payouts, remittances.

  • To find which wallet funded a Pay payment — pass wallet_type or read the rendered wallet name (funding/spot/fiat/card/earn).

When NOT to Use:

  • For a span over 90 days, or to page past the first 100 rows of a dense window — use binance_get_pay_history, which walks and bisects the window for you.

  • To see Binance Card POS spend — no endpoint returns that (03-card-and-gaps.md §1); this only shows card-funded Pay payments, not card terminal purchases.

Returns: Markdown list (or JSON) of transactions: time, orderType, signed amount (+ income / - expenditure) and currency, walletType name, the counterparty name, and transactionId. Markdown display is capped at 50 rows with a note pointing at a narrower window or binance_get_pay_history; response_format="json" always carries every row this call fetched (still limit-capped by the API itself, <= 100).

Pagination/Windows: start_time/end_time accept an ms epoch, a >=12-digit epoch-ms string, or an ISO-8601 string. Give both together (span <= 90 days) or neither — Binance's behavior for a single bound is undocumented for this endpoint, so a lone bound is rejected locally with a clear Error: rather than sent on. When both are omitted, Binance returns the most recent 90 days. limit is <= 100 (this endpoint's own max).

Examples: params = {"wallet_type": 4} # only card-funded Pay payments params = {"start_time": "2026-06-01", "end_time": "2026-08-01"}

Error Handling: -1127 means the startTime/endTime span exceeds Binance's cap (should not happen — this tool validates first); -2015 means the key lacks permission or the IP is not on the key's allowlist.

binance_get_pay_historyA

Walk up to 18 months of Binance Pay history, past the 90-day / 100-row API caps.

Repeatedly calls GET /sapi/v1/pay/transactions (UID weight 3000 per call) in <=89-day windows, newest-first, from since (default: Binance's 18-month lookback plus a two-day margin; an older since is clamped to it) up to now, or up to a resume_before cursor from a previous truncated call. A window that comes back with exactly 100 rows (the page limit) is bisected — split at its midpoint and re-walked — so a dense period is not silently dropped; if bisection reaches its 1 ms floor and STILL gets a full page, those extra rows are dropped and the response says so (possibly_incomplete). Spends at most max_calls requests (default 30 = 90,000 UID) before stopping; the returned resume_before cursor always marks the boundary of the next unfetched range (never derived from which rows happened to come back), and is omitted (no_progress) on the rare case the budget ran out before even the newest window could make any progress — resuming then would just repeat the same calls, so raise max_calls instead.

Binance Card spending is NOT available via API; card-funded Pay payments appear here with walletType 4 or 6 ("card").

When to Use:

  • To pull a full Pay history for reconciliation without hand-rolling the 90-day windowing or the 100-row-per-window cap.

  • To resume a previous run that stopped early — pass the same since plus its resume_before back in.

When NOT to Use:

  • For a single recent window — binance_get_pay_transactions is one call and cheaper.

Returns: Markdown (or JSON) list of transactions deduped by transactionId (scoped to this one call — not a persistent cross-call dedupe) sorted newest-first, the number of API calls spent, and — when the budget ran out before reaching since — a resume_before cursor to pass back on the next call alongside the same since. Markdown display is capped at 50 rows; response_format="json" always carries the full set collected by this call (only clip_response's byte cap applies).

Pagination/Windows: since accepts an ms epoch, a >=12-digit epoch-ms string, or an ISO-8601 string, default now minus 18 months (+2 days); anything older is clamped to that floor and reported as since_clamped. Each top-level window is at most 89 days (under Binance's 90-day cap); a window may cost more than one call if it has to be bisected, so max_calls bounds total calls, not windows. resume_before is always the boundary of the next unfetched range, so a resumed call never re-walks already-collected ranges (aside from harmless dedupe-caught edge overlaps).

Examples: params = {} # last 18 months, up to 30 calls params = {"since": "2026-01-01", "resume_before": 1700000000000, "max_calls": 10}

Error Handling: A request failure mid-walk does NOT discard what was already fetched: the rows collected so far come back with resume_before (the boundary of the next unfetched range) and the failure itself in stop_error — fix the cause, then call again with the same since and that resume_before. no_progress: true with no cursor means nothing was collected before the failure — clear the cause and repeat the same call. A range that ends before Binance's 18-month lookback is refused locally (nothing in it is retrievable). -2015 means the key lacks permission or the IP is not on the key's allowlist.

binance_get_earn_flexible_positionsA

List the caller's Simple Earn Flexible subscriptions and their live APR.

Calls GET /sapi/v1/simple-earn/flexible/position (SIGNED, USER_DATA). IP weight 150 per call (S1 spec, 2024-10 — Binance's docs site renders the Simple Earn pages empty, so this weight was not re-verified; treat it as approximate).

When to Use:

  • To see which Flexible products you are subscribed to, how much is deposited, and the current (and tiered, when Binance returns tiers) annual percentage rate.

  • Before deciding whether to redeem or top up a Flexible position.

When NOT to Use:

  • For time-locked Simple Earn products — use binance_get_earn_locked_positions.

  • For a single aggregate balance across all Earn products — use binance_get_earn_account.

Returns: A markdown list (or JSON with response_format="json") of positions: asset, product id, deposited amount, latest APR, tiered APR breakdown (when present), yesterday's airdrop rate, redeemability, auto-subscribe flag, and cumulative rewards (yesterday, real-time, bonus, total).

Pagination: limit (Binance size, max 100, default 20) and offset (house-style; see the module docstring for the offset -> current page-number mapping). total from Binance drives has_more. Display is additionally capped at MAX_DISPLAY_ROWS (50) even when limit asked for more — a truncation note is appended when rows were dropped.

Examples: params = {"asset": "USDT", "limit": 20} params = {"product_id": "BTC001"}

Error Handling: -2015 means the key lacks Simple Earn / USER_DATA permission, or this machine's IP is not on the key's allowlist. An empty rows list means no Flexible subscriptions exist (or the asset/product_id filter matched nothing).

binance_get_earn_locked_positionsA

List the caller's Simple Earn Locked subscriptions and their APY/redeem dates.

Calls GET /sapi/v1/simple-earn/locked/position (SIGNED, USER_DATA). IP weight 150 per call (S1 spec, 2024-10 — same unverified caveat as binance_get_earn_flexible_positions; treat it as approximate).

When to Use:

  • To see time-locked Earn positions: duration, accrued days, APY, and redeem date.

  • Before deciding whether to let a position auto-renew or opt out.

When NOT to Use:

  • For on-demand redeemable positions — use binance_get_earn_flexible_positions.

  • For a single aggregate balance — use binance_get_earn_account.

Returns: A markdown list (or JSON) of positions: asset, position id, project id, amount, APY, duration/accrued days, reward asset, purchase and redeem dates, and the renewable/auto-renew flags.

Pagination: Same limit/offset -> Binance size/current mapping as binance_get_earn_flexible_positions (see the module docstring).

Examples: params = {"asset": "AXS"} params = {"position_id": "123123"}

Error Handling: -2015 as above (permission or IP allowlist). An empty rows list means no Locked subscriptions match the filters.

binance_get_earn_accountA

Summarize total Simple Earn holdings (Flexible + Locked) in BTC and USDT.

Calls GET /sapi/v1/simple-earn/account (SIGNED, USER_DATA). IP weight 150 per call (S1 spec, 2024-10 — same unverified caveat as the position tools above).

When to Use:

  • For a one-call snapshot of total Earn value without listing every position.

When NOT to Use:

  • To see individual products or positions — use binance_get_earn_flexible_positions / binance_get_earn_locked_positions.

Returns: A markdown block (or JSON with response_format="json") with total, flexible-only, and locked-only amounts, each in BTC and USDT.

Examples: params = {} params = {"response_format": "json"}

Error Handling: -2015 means the key lacks Simple Earn / USER_DATA permission or this machine's IP is not on the key's allowlist. All-zero amounts mean no funds are in Simple Earn.

binance_get_spot_accountA

Get spot account state: trade/withdraw/deposit flags, commission rates, balances.

Calls GET /api/v3/account (SIGNED, USER_DATA). IP weight 20 per call.

When to Use:

  • To check current spot balances (free + locked) for one or all assets.

  • To confirm whether the account can currently trade, withdraw, or deposit, and what its maker/taker/buyer/seller commission rates are.

When NOT to Use:

  • For a specific symbol's commission (with any special/discount overrides) — use binance_get_commission_rates.

  • For non-spot wallets (Funding, Earn, ...) — use the wallet-account tools.

Returns: A markdown block (or JSON with response_format="json") with canTrade/ canWithdraw/canDeposit, account type, commissionRates (maker/taker/buyer/ seller via fmt_num), permissions, last update time, and the balances list (free/locked via fmt_num). When omit_zero_balances is True (the default) and no asset filter is given, a count of hidden zero-balance assets is shown. Display is capped at MAX_DISPLAY_ROWS (50) with a truncation note; JSON mode instead adds truncated/balancesShown/balancesMatched fields so truncation is machine-readable too.

Examples: params = {} params = {"omit_zero_balances": False} params = {"asset": "USDT"}

Error Handling: -2015 means the key lacks Reading permission or this machine's IP is not on the key's allowlist. An empty balances list after filtering means the asset filter matched nothing, or every balance was zero and got hidden.

binance_get_commission_ratesA

Get the account's standard/special/tax commission rates for one symbol.

Calls GET /api/v3/account/commission (SIGNED, USER_DATA). IP weight 20 per call.

When to Use:

  • To see the exact maker/taker/buyer/seller commission that will apply on a given symbol, including any special-tier override, tax commission, or a BNB-style fee discount.

When NOT to Use:

  • For the account's default (non-symbol-specific) commission rates — use binance_get_spot_account, which echoes commissionRates too.

Returns: A markdown block (or JSON) with the symbol, standard/special/tax commission blocks (maker/taker/buyer/seller via fmt_num), and the discount block (enabled-for-account, enabled-for-symbol, discount asset, rate).

Examples: params = {"symbol": "BTCUSDT"}

Error Handling: -1121 means an invalid or unknown symbol — check binance_get_exchange_info. -2015 means the key lacks Reading permission or the IP is not allowlisted.

binance_get_order_rate_limitsA

Get the account's current order-rate-limit usage (per-second/day order counts).

Calls GET /api/v3/rateLimit/order (SIGNED, USER_DATA). IP weight 40 per call — noticeably heavier than the other tools in this module; do not poll this tightly.

When to Use:

  • Before a burst of order placements, to see how much of the ORDERS rate limit (per interval, e.g. 10s/1d) has already been used.

  • To debug a -1015 "Too many orders" rejection.

When NOT to Use:

  • For the exchange-wide REQUEST_WEIGHT/RAW_REQUESTS limits — those come back in every response's rate-limit headers, not from this endpoint.

Returns: A markdown list (or JSON) of {rateLimitType, interval, intervalNum, limit, count} entries — one per configured ORDERS rate-limit window.

Examples: params = {}

Error Handling: -2015 means the key lacks Reading permission or the IP is not allowlisted.

binance_get_prevented_matchesA

List orders rejected by Self-Trade Prevention (STP) for a symbol.

Calls GET /api/v3/myPreventedMatches (SIGNED, USER_DATA). IP weight 2 when queried by prevented_match_id, 20 when queried by order_id.

When to Use:

  • To see which of your own orders were prevented from matching against each other (STP), including the price and quantity that was blocked.

  • To audit STP behavior for a specific order via order_id.

When NOT to Use:

  • For orders that DID execute — use binance_get_my_trades (trade history).

Returns: A markdown list (or JSON) of prevented matches: preventedMatchId, tradeGroupId, taker/maker order ids, maker symbol, price, maker quantity prevented (via fmt_num), the self-trade-prevention mode, and the transaction time. Display is capped at MAX_DISPLAY_ROWS (50); JSON mode returns {count, truncated, displayLimit, items} rather than a bare array, so truncation stays valid JSON.

Pagination: Only valid together with order_id: from_prevented_match_id is an inclusive cursor — pass the last-seen preventedMatchId (or one past it) to page forward, and limit (only sent when from_prevented_match_id is set; Binance default 500, max 1000) caps how many rows come back per call. Display is additionally capped at MAX_DISPLAY_ROWS (50) regardless of limit.

Examples: params = {"symbol": "BTCUSDT", "prevented_match_id": 1} params = {"symbol": "BTCUSDT", "order_id": 12345, "from_prevented_match_id": 5}

Error Handling: Exactly one of prevented_match_id or order_id is required — validated locally before the call. from_prevented_match_id requires order_id. -1121 means an invalid symbol; -2013/-2011 mean the order id does not exist.

binance_get_allocationsA

List Smart Order Routing (SOR) allocations — the per-symbol fills behind an SOR order.

Calls GET /api/v3/myAllocations (SIGNED, USER_DATA). IP weight 20 per call.

When to Use:

  • To see how an SOR order (binance_place_sor_order) was actually filled across symbols, with per-allocation price/qty/commission.

  • To page through allocations for a specific order via order_id.

When NOT to Use:

  • For regular (non-SOR) trade fills — use binance_get_my_trades.

Returns: A markdown list (or JSON) of allocations: allocationId, orderId/orderListId, symbol, side (isBuyer), qty/price/quoteQty (via fmt_num), commission + commissionAsset, maker/allocator flags, and time. Display is capped at MAX_DISPLAY_ROWS (50); JSON mode returns {count, truncated, displayLimit, items} rather than a bare array, so truncation stays valid JSON.

Windows: start_time/end_time (epoch ms or ISO-8601) accept a span of at most 24 h — enforced locally with a readable Error: before the call reaches Binance, since Binance would otherwise answer -1127.

Examples: params = {"symbol": "BTCUSDT"} params = {"symbol": "BTCUSDT", "start_time": "2024-01-01T00:00:00Z", "end_time": "2024-01-01T12:00:00Z"} params = {"symbol": "BTCUSDT", "order_id": 12345}

Error Handling: -1127 means the requested window is too wide (should not happen — the 24 h cap is enforced before the request). -1121 means an invalid symbol.

binance_place_twap_orderA

Place a REAL spot TWAP algo order on Binance. This spends real money.

Calls POST /sapi/v1/algo/spot/newOrderTwap (SIGNED, UID weight 3000 of a 180,000/min budget — call it sparingly). Binance splits quantity into sub-orders and works them over duration seconds, aiming at the time-weighted average price instead of taking the book in one hit.

Kill-switch. This call is refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1. The gate lives in the HTTP client, so no tool can bypass it. If you see that error, the operator has deliberately put the server in read-only mode — report it, do not try to work around it.

Binance's own constraints, all rejected server-side if broken:

  • duration 300-86400 seconds (5 minutes to 24 hours) — checked locally too.

  • Minimum notional ≈ 1,000 USDT equivalent per algo order (the docs also quote a per-symbol maximum of 200k / 2mm / 10mm; let the API arbitrate the ceiling).

  • At most 20 open algo orders at a time — check with binance_get_open_algo_orders before adding another.

  • client_algo_id, when supplied, must be exactly 32 characters.

success: true means ACCEPTED, NOT EXECUTED. The response carries no fill information at all; it only says Binance took the order. What actually traded is visible through binance_get_open_algo_orders, binance_get_algo_order_history and binance_get_algo_sub_orders.

When to Use:

  • Working a position that is large relative to the book, where a single MARKET order would move the price against you.

  • Spreading an entry or exit over minutes or hours on purpose.

When NOT to Use:

  • For an ordinary immediate or resting order — use binance_place_order (spot_orders.py); it is weight 1, not 3000, and has no notional floor.

  • Below ~1,000 USDT of notional — the API rejects it; place a normal order instead.

  • For USDⓈ-M / COIN-M futures TWAP or VP — that is a different product on a different wallet and this server does not implement it.

Returns: A confirmation echoing exactly the four fields Binance returned — clientAlgoId, success, code, msg — plus an explicit note that the order is accepted and not executed, and which tool to poll. A success: false body (Binance answers those with HTTP 200) is rendered as Error: <msg> (code <code>), never as a confirmation.

Examples: params = {"symbol": "BTCUSDT", "side": "BUY", "quantity": "0.5", "duration": 3600} params = {"symbol": "BTCUSDT", "side": "SELL", "quantity": "1.25", "duration": 7200, "limit_price": "65000.00", "client_algo_id": "abcdefghijklmnopqrstuvwxyz012345"}

Error Handling:

  • Error: … trading is disabled … → the kill-switch is off; nothing was sent.

  • A duration outside 300-86400 or a 31-character client_algo_id fails locally, before anything is signed.

  • -2010 / -1013 point at balance, the notional floor or a symbol filter; -2015 means the key lacks Spot & Margin Trading permission or this IP is not allowlisted.

  • A 5xx or a timeout means the execution status is UNKNOWN — the algo order may well be live. Check binance_get_open_algo_orders (and binance_get_algo_order_history) before doing anything else. NEVER resend blindly: a duplicate TWAP is a second position, and each one eats one of the 20 slots.

binance_cancel_algo_orderA

Cancel a working spot TWAP algo order.

Calls DELETE /sapi/v1/algo/spot/order (SIGNED, IP weight 1). Pass exactly one id: algo_id (Binance's numeric algoId) or client_algo_id (the 32-character id you supplied when placing). Both at once is refused locally — on a destructive call an ambiguous request is worse than a refused one.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1.

Cancelling is idempotent in effect: a second cancel of the same algo order changes nothing and comes back as a rejection. What it cannot undo is what already traded — the sub-orders already filled stay filled, and only the unexecuted remainder is called off. Read binance_get_algo_sub_orders to see what that remainder is.

When to Use:

  • Stopping a TWAP whose thesis no longer holds, mid-execution.

  • Freeing one of the 20 open-algo-order slots.

When NOT to Use:

  • To cancel an ordinary spot order — that is binance_cancel_order (spot_orders.py); these endpoints do not see each other's orders.

  • Before checking what is open — binance_get_open_algo_orders is free of consequence and gives you the algoId this tool needs.

Returns: A confirmation echoing exactly the four fields Binance returned — algoId, success, code, msg — with no claim about how much of the order had executed. A success: false body (HTTP 200) is rendered as Error: <msg> (code <code>).

Examples: params = {"algo_id": 14511} params = {"client_algo_id": "abcdefghijklmnopqrstuvwxyz012345"}

Error Handling: A rejection usually means the algo order is not cancellable: already finished, already cancelled, or the id belongs to another account. -2015 means the key lacks Spot & Margin Trading permission or this IP is not allowlisted. A 5xx/timeout leaves the cancel UNKNOWN — re-read binance_get_open_algo_orders before assuming either way.

binance_get_open_algo_ordersA

List the spot TWAP algo orders that are still working, across every symbol.

Calls GET /sapi/v1/algo/spot/openOrders (SIGNED, IP weight 1). It takes no filters: one call returns everything currently running, which is also how you check the 20 open algo orders ceiling before placing another.

When to Use:

  • Right after binance_place_twap_order, to confirm the order is actually working — the placement response only says "accepted".

  • Before placing a new TWAP, to see how many of the 20 slots are free.

  • After a 5xx/timeout on a placement, to find out whether the order exists.

When NOT to Use:

  • For orders that have finished — use binance_get_algo_order_history.

  • For the fills of one order — use binance_get_algo_sub_orders.

  • For ordinary spot orders — use binance_get_open_orders (spot_orders.py); algo and ordinary orders live in separate endpoints and neither lists the other.

Returns: A markdown table (bookTime, algoId, symbol, side, algoStatus, algoType, totalQty, executedQty, executedAmt, avgPrice, urgency, endTime) capped at 50 rows, or the raw {total, orders[]} payload with response_format="json" (which also carries clientAlgoId).

Examples: params = {} params = {"response_format": "json"}

Error Handling: An empty list is a valid answer: nothing is working. -2015 means the key lacks Reading permission or this IP is not allowlisted. /sapi does not exist on the spot testnet — a 404 there is expected, not a bug.

binance_get_algo_order_historyA

List finished spot TWAP algo orders — filled, cancelled or expired.

Calls GET /sapi/v1/algo/spot/historicalOrders (SIGNED, IP weight 1). Every filter is optional: symbol, side, start_time, end_time. Binance's older reference marks symbol and side as mandatory; the current per-endpoint page makes both optional, which is what this tool follows — omit them for the whole account.

No maximum window is documented for this endpoint, so none is enforced here.

When to Use:

  • Reviewing how a TWAP actually executed once it is no longer open.

  • Reconciling a period: what algo orders ran, on what symbols, for how much.

When NOT to Use:

  • For orders still working — binance_get_open_algo_orders.

  • For the individual fills and fees of one order — binance_get_algo_sub_orders; a row here only carries the aggregate.

  • For ordinary spot order history — binance_get_all_orders (spot_orders.py).

Returns: A markdown table (bookTime, algoId, symbol, side, algoStatus, algoType, totalQty, executedQty, executedAmt, avgPrice, urgency, endTime) capped at 50 rows, or the raw {total, orders[]} payload with response_format="json" (which also carries clientAlgoId).

Pagination: page (1-based) and page_size (1-100, default 100) map to Binance's page / pageSize. Only 50 rows are rendered, so a full 100-row page hides rows 51-100: lower page_size to 50, or use response_format="json", for the rest.

Examples: params = {} params = {"symbol": "BTCUSDT", "side": "BUY", "page_size": 20} params = {"start_time": "2026-09-01", "end_time": "2026-09-23T23:59:59Z"}

Error Handling: start_time / end_time accept epoch ms or ISO-8601; anything else fails locally with a readable message. -2015 means the key lacks Reading permission or this IP is not allowlisted. /sapi does not exist on the spot testnet.

binance_get_algo_sub_ordersA

List the individual orders a TWAP placed on the book, with fills and fees.

Calls GET /sapi/v1/algo/spot/subOrders (SIGNED, IP weight 1). A TWAP is executed as a stream of ordinary orders; this is the only place to see them — what each slice filled, at what average price, and what it cost in fees.

When to Use:

  • Answering "what did this TWAP actually get me?" — the executedQty / executedAmt / fee totals for one algoId.

  • Auditing a cancelled TWAP: what traded before the cancel landed.

When NOT to Use:

  • To find the algoId in the first place — that comes from binance_get_open_algo_orders or binance_get_algo_order_history.

  • For a symbol-wide trade list — binance_get_my_trades (trade_history.py) covers every fill, algo or not.

Returns: The order-level totals (total, executedQty, executedAmt) followed by a table of sub-orders: bookTime, subId, orderId, symbol, side, orderStatus, executedQty, executedAmt, avgPrice and the fee with its asset.

Pagination: page (1-based) and page_size (1-100, default 100) map to Binance's page / pageSize. Only 50 rows are rendered, so a full 100-row page hides rows 51-100: lower page_size to 50, or use response_format="json", for the rest.

Examples: params = {"algo_id": 14511} params = {"algo_id": 14511, "page": 2, "page_size": 50}

Error Handling: An unknown algoId comes back as a Binance rejection, not an empty page. An empty subOrders array means the TWAP has not traded yet. -2015 means the key lacks Reading permission or this IP is not allowlisted. /sapi does not exist on the spot testnet.

binance_test_orderA

Validate an order against Binance's filters WITHOUT sending it to the order book.

Calls POST /api/v3/order/test (SIGNED, IP weight 1 — 20 with compute_commission_rates). Binance runs the same validation as a real placement (signature, recvWindow, symbol status, LOT_SIZE / PRICE_FILTER / NOTIONAL, balance rules) and returns {} on success: nothing is matched, nothing rests on the book, no funds move.

This tool is always allowed. It is on the client's POST_READ_ALLOWLIST, so it works with the trading kill-switch off (BINANCE_ALLOW_TRADING unset) — which makes it the right first step before every binance_place_order call.

When to Use:

  • Always, immediately before placing a real order, to catch a filter or precision error for free.

  • With compute_commission_rates=true to learn the fee rates that would apply.

When NOT to Use:

  • To actually trade — that is binance_place_order.

  • To check a symbol's filters in the abstract — binance_get_exchange_info (market_data.py) lists tick size, step size and min notional directly.

Returns: A confirmation that the order passed validation (and the commission-rate breakdown when requested). A rejection comes back as an Error: line quoting Binance's reason.

Examples: params = {"symbol": "BTCUSDT", "side": "BUY", "type": "LIMIT", "time_in_force": "GTC", "quantity": "0.001", "price": "20000.00"} params = {"symbol": "BTCUSDT", "side": "SELL", "type": "MARKET", "quantity": "0.001", "compute_commission_rates": True}

Error Handling: -1013/-2010 point at a symbol filter (step size, tick size, min notional); -1111 is a precision error — check binance_get_exchange_info. -2015 means the key lacks Spot Trading permission or this IP is not allowlisted. The per-type mandatory parameter sets are checked locally, so those failures never reach Binance.

binance_place_orderA

Place a REAL spot order on Binance. This spends real money.

Calls POST /api/v3/order (SIGNED, IP weight 1, unfilled-order count 1). A MARKET order executes immediately at whatever the book offers; a LIMIT order rests until it fills, expires or is cancelled.

Kill-switch. This call is refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1. The gate lives in the HTTP client, so no tool can bypass it. If you see that error, the operator has deliberately put the server in read-only mode — report it, do not try to work around it.

Always run binance_test_order first with identical parameters: it is allowed even with the kill-switch off and catches filter/precision rejections for free.

When to Use:

  • After a dry-run passed and the human has approved this specific order.

  • To act on a decision that already names symbol, side, type, quantity and price.

When NOT to Use:

  • To "see if it would work" — that is binance_test_order.

  • For a bracket/OCO (entry plus stop plus target) — use the order-list tools in order_lists.py, which place the legs atomically.

  • To modify a resting order — use binance_cancel_replace_order, which does not leave you unhedged between the two calls.

Returns: A confirmation echoing exactly what Binance returned: symbol, orderId, clientOrderId, status, executedQty, cummulativeQuoteQty, and the fills table when the response carries one. Nothing is inferred: with new_order_resp_type="ACK" Binance reports only the ids, and the confirmation says so rather than implying a fill. When Binance answers EXPIRED / EXPIRED_IN_MATCH / REJECTED the heading reads Order NOT live — an IOC/FOK that never rested is not a placed order.

Examples: params = {"symbol": "BTCUSDT", "side": "BUY", "type": "LIMIT", "time_in_force": "GTC", "quantity": "0.001", "price": "20000.00", "new_client_order_id": "my-entry-001"} params = {"symbol": "BTCUSDT", "side": "SELL", "type": "MARKET", "quantity": "0.001"} params = {"symbol": "BTCUSDT", "side": "SELL", "type": "STOP_LOSS_LIMIT", "time_in_force": "GTC", "quantity": "0.001", "price": "19000.00", "stop_price": "19100.00"}

Error Handling:

  • Error: … trading is disabled … → the kill-switch is off; nothing was sent.

  • -2010 (order rejected) → insufficient balance, or a symbol filter: quantity off the LOT_SIZE step, price off the PRICE_FILTER tick, or the order under the NOTIONAL minimum. Read the filters with binance_get_exchange_info and re-run the dry-run.

  • -1013 / -1111 are the same family (precision / filter).

  • -2021 means a LIMIT_MAKER would have taken liquidity immediately.

  • A 5xx or a timeout means the execution status is UNKNOWN — the order may well be live. Query it with binance_get_order (by new_client_order_id if you set one) or binance_get_open_orders before doing anything else. NEVER resend blindly: a duplicate market order is real money lost.

binance_get_orderA

Look up one order — open, filled, cancelled or expired — by id.

Calls GET /api/v3/order (SIGNED, IP weight 4). Pass the symbol plus exactly one id: order_id (Binance's numeric orderId) or orig_client_order_id (the id you supplied when placing). Both at once is rejected locally: Binance searches orderId first and would silently ignore a mismatched client id.

When to Use:

  • After a 5xx or a timeout on a placement — this is how you find out whether the order exists before considering a retry.

  • To check the final state of an order that is no longer open.

When NOT to Use:

  • To list what is currently resting — use binance_get_open_orders.

  • To page through history — use binance_get_all_orders.

  • For the individual trades that filled the order — use binance_get_my_trades (trade_history.py).

Returns: A markdown detail block (status, side, type, prices, quantities, timestamps), or the raw Binance object with response_format="json".

Examples: params = {"symbol": "BTCUSDT", "order_id": 123456789} params = {"symbol": "BTCUSDT", "orig_client_order_id": "my-entry-001"}

Error Handling: -2011/-2013 mean no such order for that symbol — check the symbol, or the order may be older than 90 days and archived (-2026). Orders are scoped per symbol: the right id on the wrong symbol looks identical to a missing order.

binance_cancel_orderA

Cancel one open spot order by id.

Calls DELETE /api/v3/order (SIGNED, IP weight 1). Pass the symbol plus exactly one id — order_id or orig_client_order_id; both at once is rejected locally because Binance would resolve the numeric id and ignore a mismatched client id.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1.

Cancelling is idempotent in effect: a second cancel of the same order returns -2011 ("unknown order") and changes nothing. What it cannot undo is a fill — use cancel_restrictions="ONLY_NEW" to make the cancel fail rather than succeed against an order that has already started filling.

When to Use:

  • To pull a resting order that is no longer wanted.

  • Before replacing an order, when you do not need the atomicity of binance_cancel_replace_order.

When NOT to Use:

  • To cancel everything on a symbol — use binance_cancel_all_open_orders (one call, one weight unit).

  • To cancel one leg of an OCO/OTO list — that cancels the whole list; use binance_cancel_order_list (order_lists.py) so the intent is explicit.

Returns: A confirmation echoing Binance's cancelled-order object: symbol, orderId, origClientOrderId, status (CANCELED), and the executed quantities at cancellation.

Examples: params = {"symbol": "BTCUSDT", "order_id": 123456789} params = {"symbol": "BTCUSDT", "orig_client_order_id": "my-entry-001", "cancel_restrictions": "ONLY_NEW"}

Error Handling: -2011 means the order is not cancellable: it does not exist, already filled, was already cancelled — or cancel_restrictions did not match its current state, which is the safe outcome, not a failure. A 5xx/timeout leaves the cancel UNKNOWN: check with binance_get_order before assuming the order is still live.

binance_cancel_all_open_ordersA

Cancel EVERY open order on one symbol, including order-list legs.

Calls DELETE /api/v3/openOrders (SIGNED, IP weight 1). This is a blunt instrument: it takes no id and cancels whatever is resting on that symbol, OCO/OTO lists included (their legs come back as order-list objects with orderReports[]).

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1.

When to Use:

  • Flattening the working orders on one symbol — a stop-out or a strategy reset.

  • When several orders must go and cancelling them one by one would race the market.

When NOT to Use:

  • When one specific order should go — use binance_cancel_order with an id.

  • To see what would be cancelled first — call binance_get_open_orders with the same symbol; that read is free of consequence and this one is not.

Returns: A confirmation listing every cancelled order, plus a section per cancelled order list (orderListId, contingencyType, and each leg from orderReports[]).

Examples: params = {"symbol": "BTCUSDT"}

Error Handling: -2011 means there was nothing open on that symbol. A 5xx/timeout leaves the outcome UNKNOWN — re-read with binance_get_open_orders rather than assuming either way.

binance_cancel_replace_orderA

Cancel one order and place its replacement in a single request.

Calls POST /api/v3/order/cancelReplace (SIGNED, IP weight 1, unfilled-order count 1). Use it to reprice a resting order without the window of exposure that a separate cancel-then-place leaves open.

Kill-switch. Refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1.

The two halves can diverge, and cancel_replace_mode decides how:

  • STOP_ON_FAILURE — if the cancel fails, the new order is never attempted.

  • ALLOW_FAILURE — the new order is attempted regardless of the cancel's outcome, so you can end up with both orders live, or neither.

HTTP 409 is the partial-success case: the cancel succeeded and the new order failed. It is returned as Error (409): Partial success … followed by the same cancelResult / newOrderResult breakdown as a success — so you can see exactly which order was cancelled. Read it as "the old order is gone, the replacement is NOT live" and re-place deliberately.

When to Use:

  • Repricing or resizing a resting limit order.

  • Rolling a stop as the market moves.

When NOT to Use:

  • For a fresh order with nothing to cancel — use binance_place_order.

  • To only pull an order — use binance_cancel_order.

  • On an order-list leg — cancel the list with binance_cancel_order_list (order_lists.py) and place a new list.

Returns: cancelResult and newOrderResult (SUCCESS / FAILURE / NOT_ATTEMPTED) plus the two response objects Binance returned, rendered separately so it is unambiguous which order is live.

Examples: params = {"symbol": "BTCUSDT", "side": "BUY", "type": "LIMIT", "time_in_force": "GTC", "quantity": "0.001", "price": "19500.00", "cancel_replace_mode": "STOP_ON_FAILURE", "cancel_order_id": 123456789} params = {"symbol": "BTCUSDT", "side": "BUY", "type": "LIMIT", "time_in_force": "GTC", "quantity": "0.002", "price": "19000.00", "cancel_replace_mode": "ALLOW_FAILURE", "cancel_orig_client_order_id": "my-entry-001", "cancel_restrictions": "ONLY_NEW"}

Error Handling: HTTP 409 = cancel succeeded, replacement failed (see above). -2021/-2022 wrap the failing half in {code, msg, data}. -2011 means the order to cancel was not cancellable (filled, gone, or cancel_restrictions did not match). A 5xx/timeout leaves BOTH halves UNKNOWN: read binance_get_open_orders for the symbol before sending anything else.

binance_get_open_ordersA

List the orders currently resting on the book.

Calls GET /api/v3/openOrders (SIGNED). Weight 6 with symbol, 80 without — the no-symbol form scans every pair and costs more than a percent of the 6000/min IP budget in one call. Pass a symbol whenever you know it.

When to Use:

  • To see what is working right now, before placing or cancelling anything.

  • After a 5xx/timeout on a placement, as a symbol-wide check when you have no id.

When NOT to Use:

  • For one known order — binance_get_order costs weight 4 and is precise.

  • For orders that are no longer open — binance_get_all_orders covers history.

Returns: A markdown table (time, symbol, orderId, side, type, status, price, origQty, executedQty, cumQuote) capped at 50 rows, or the raw array with response_format="json".

Examples: params = {"symbol": "BTCUSDT"} params = {}

Error Handling: -2015 means the key lacks permission or this IP is not allowlisted. An empty list is a valid answer: nothing is resting.

binance_get_all_ordersA

List a symbol's orders — open, filled, cancelled and expired alike.

Calls GET /api/v3/allOrders (SIGNED, IP weight 20). Two ways to narrow it: order_id as a cursor (returns orders with orderId >= it) or a start_time/ end_time window. The window may not exceed 24 hours — that cap is checked here, before the call, so you get a clear message instead of Binance's -1127. Walk a longer span in 24 h slices, or page by order_id.

When to Use:

  • Reconstructing what happened on a symbol in a given day.

  • Paging order history forward with an order_id cursor.

When NOT to Use:

  • For what is open right now — binance_get_open_orders (weight 6 with a symbol).

  • For the actual fills, fees and trade ids — binance_get_my_trades (trade_history.py); an order row only carries aggregates.

Pagination: limit is 1-1000 (Binance default 500) and at most 50 rows are rendered; use response_format="json" or narrow the window for the rest. order_id pages forward: pass the last orderId you saw, plus one.

Windows: start_time/end_time accept epoch ms or ISO-8601 and must span 24 h or less together. Omit both to get the most recent limit orders. Orders with no fill are archived after 90 days and stop being returned.

Examples: params = {"symbol": "BTCUSDT"} params = {"symbol": "BTCUSDT", "start_time": "2026-09-22T00:00:00Z", "end_time": "2026-09-22T23:59:59Z", "limit": 1000} params = {"symbol": "BTCUSDT", "order_id": 123456789}

Error Handling: A window wider than 24 h is rejected locally. -1127 from Binance means the same thing reached it anyway; -1121 is an unknown symbol. -2015 means the key lacks permission or this IP is not allowlisted.

binance_get_my_tradesA

Fetch YOUR executed trades (fills) for one symbol.

Calls GET /api/v3/myTrades (signed; IP weight 20, or 5 when order_id is given). symbol is mandatory — Binance has no endpoint that returns trades across every symbol, which is what binance_get_all_my_trades exists to work around.

Unlike the public trade endpoints, isBuyer here is your own side of the fill (public trades expose isBuyerMaker, the aggressor's side, instead).

When to Use:

  • To see the fills of one pair, or of one order (order_id).

  • To check the exact price, fee and fee asset of a known trade.

When NOT to Use:

  • For the whole account's history — use binance_get_all_my_trades.

  • For orders that never filled — use binance_get_all_orders (spot_orders).

  • For anonymous market trades — use binance_get_recent_trades (market_data).

Returns: Markdown: a table of up to 100 fills (time, side, price, qty, quote qty, commission, maker/taker) plus totals for the page — bought/sold base and quote, and fees broken down by fee asset. JSON: the full page plus the same totals.

Pagination / Windows: Binance accepts only these combinations: symbol; symbol+order_id; symbol+from_id; symbol+start_time; symbol+end_time; symbol+start_time+end_time; symbol+order_id+from_id. start_time and end_time are each legal on their own — only together do they have to span at most 24 hours, and a wider window is rejected here with no call spent. To page, re-call with from_id = the last id + 1.

Examples: params = {"symbol": "BTCUSDT", "limit": 100} params = {"symbol": "BTCUSDT", "order_id": 987654321} params = {"symbol": "ETHUSDT", "start_time": "2024-01-01T00:00:00Z", "end_time": "2024-01-01T23:59:59Z"} params = {"symbol": "ETHUSDT", "from_id": 4211999}

Error Handling: An over-wide window or an illegal combination is refused locally with an Error: … string and no API call. -2015 means the key lacks Reading or the IP is not allowlisted; -1121 means the symbol does not exist.

binance_discover_traded_symbolsA

Work out which symbols this account plausibly traded — Binance will not tell you.

There is no endpoint that lists an account's traded pairs. Binance staff answered the question twice on their own developer forum, and both answers are workarounds: keep a local record from the user-data websocket stream, or infer the pairs from the account's assets (dev.binance.vision threads 4810 and 4329). This tool is the second answer, made cheap.

It unions the assets the account visibly holds or held — GET /api/v3/account (weight 20, zero balances omitted), POST /sapi/v3/asset/getUserAsset (weight 5, the funding/spot asset list) and GET /sapi/v1/asset/dribblet (weight 1, the last 100 dust conversions) — then crosses them with every exchangeInfo symbol (weight 20, fetched once per process and cached) whose base asset is a candidate and whose quote asset is either whitelisted (quote_assets) or itself a candidate. Total discovery cost: ~46 IP weight of the 6000/min budget.

Blind spot, stated plainly: the match is on the base asset, so an asset bought and then fully sold within spot — never deposited, withdrawn or dust-converted — leaves no trace to discover, and its pair is missed. Name it in extra_assets. Matching on the quote side too would not rescue it and costs a fortune: on the real exchangeInfo, USDT alone drags in 493 TRADING pairs (9,860 weight).

When to Use:

  • Before binance_get_all_my_trades, to see (and prune) the symbol list and its cost.

  • To answer "which pairs have I ever traded?" without spending 74,000 weight.

When NOT to Use:

  • When you already know the pairs — pass them to binance_get_all_my_trades directly.

  • To read balances — use binance_get_spot_account / binance_get_user_assets.

Returns: Markdown: the candidate assets with their source counts, the sorted symbol list, and the estimated cost of walking it (20 IP weight per symbol). JSON: the same, as {"assets": [...], "symbols": [...], "estimated_weight": N}.

Examples: params = {} params = {"extra_assets": ["SOL", "ADA"], "quote_assets": ["USDT", "BTC"]} params = {"include_break": true}

Error Handling: /sapi endpoints do not exist on the spot testnet (404). -2015 means the key lacks Reading or the IP is not allowlisted.

binance_get_all_my_tradesA

Collect every fill across every symbol this account traded — the "all my trades" answer.

Binance has no such endpoint (myTrades needs a symbol; staff confirm the gap on dev.binance.vision threads 4810 and 4329), so this tool does the only thing that works over REST: take a symbol list — yours, or one from binance_discover_traded_symbols — and walk each symbol by fromId at 1000 fills a page until a short page says that symbol is exhausted.

Two brakes keep it inside the 6000/min IP budget. max_weight (default 3000 = 150 pages) is checked before every request, and the walk also stops when Binance's own reported used weight passes weight_ceiling (default 5000). When either fires — or when a request errors mid-walk — the fills collected so far are returned together with a cursor, so nothing is lost and the next run resumes exactly there.

Cost, so nobody is surprised: 20 IP weight per page per symbol. 150 symbols with no trades still costs 3000 weight. Walking all 1370 TRADING symbols would cost 27,400 — about five minutes of full budget — which is why discovery narrows the list first.

When to Use:

  • "Show me every trade I have ever made", tax/portfolio reconstruction, a full export.

  • Incremental top-ups: keep the returned cursor and pass it back next time.

When NOT to Use:

  • For one pair — binance_get_my_trades is one call.

  • For orders that never filled, deposits, withdrawals, converts or Pay/Card spending: those are different endpoints (spot_orders, wallet_capital, convert, pay).

Returns: Markdown: the walk status (symbols finished, calls, weight), a time-sorted table of up to 200 fills, per-symbol totals (fills, bought/sold base and quote, fees by asset) and the next cursor as a JSON block to paste back. JSON: the same data with every fill.

Pagination: cursor maps symbol → the last trade id already collected; the walk restarts each symbol at that id + 1, so re-running is cheap and never duplicates a fill. Symbols the budget never reached keep whatever position the cursor already held. A symbol that returns no trades gets no cursor entry, so every incremental run re-checks it from scratch at 20 weight a time — drop the empties from symbols once you know them.

Examples: params = {} params = {"symbols": ["BTCUSDT", "ETHUSDT"], "max_weight": 200} params = {"symbols": ["BTCUSDT"], "cursor": {"BTCUSDT": 4211999}}

Error Handling: An error mid-walk never discards work: the partial fills plus the cursor come back alongside the error text. -2015 means the key lacks Reading or the IP is not allowlisted; a 429/418 means the budget was already spent elsewhere — lower weight_ceiling and wait a minute.

binance_get_account_statusA

Report whether the account is in good standing with Binance.

Calls GET /sapi/v1/account/status (SIGNED, IP weight 1). Binance flags accounts that trip abuse/AML controls (e.g. excessive order cancellation) here; a healthy account reports "Normal".

When to Use:

  • Before an automated trading run, to confirm the account is not under review.

  • Alongside binance_get_api_trading_status when diagnosing rejected orders.

When NOT to Use:

  • To read API-key permission flags — use binance_get_api_restrictions.

  • To read trading-specific locks/triggers — use binance_get_api_trading_status.

Returns: A one-line markdown status, or the raw JSON envelope with response_format="json".

Examples: params = {} params = {"response_format": "json"}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_api_trading_statusA

Report whether spot trading is locked and what triggered it.

Calls GET /sapi/v1/account/apiTradingStatus (SIGNED, IP weight 1). When Binance's abuse-prevention system trips (excessive cancel ratio, etc.) it locks trading for a cooldown window; this reports the lock state, the recovery ETA, and which trigger fired.

When to Use:

  • When order placement starts failing for no obvious filter/balance reason, to check for a temporary account-wide trading lock.

When NOT to Use:

  • To check the account's general standing — use binance_get_account_status.

  • To check key permission flags — use binance_get_api_restrictions.

Returns: A markdown block with isLocked, the planned recovery time (rendered UTC), and the trigger-condition thresholds (GCR = GTC cancellation ratio, IFER = IOC/FOK expiration ratio, UFR = unfilled ratio), or raw JSON with response_format="json".

Examples: params = {}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_api_restrictionsA

Report the full permission flag set on the configured API key.

Calls GET /sapi/v1/account/apiRestrictions (SIGNED, IP weight 1) and renders every flag Binance returns, with the same warning wording as binance_health_check for a withdrawals-enabled or no-IP-allowlist key.

When to Use:

  • To audit a key end-to-end — this is the full flag list.

  • Before enabling BINANCE_ALLOW_TRADING, to confirm trading is permitted and withdrawals are off.

When NOT to Use:

  • For a quick post-startup connectivity+permissions check — use binance_health_check, which already calls this endpoint as part of a broader check.

Returns: A markdown flag list (⚠️ next to anything risky), or raw JSON with response_format="json".

Examples: params = {}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_account_infoA

Report the account's VIP tier and which product lines are enabled.

Calls GET /sapi/v1/account/info (SIGNED, IP weight 1).

When to Use:

  • To check the account's VIP fee tier, or whether margin/futures/options are enabled before routing a request that assumes one of them.

When NOT to Use:

  • To read balances or trading permissions — use binance_get_spot_account (spot_account.py) or binance_get_api_restrictions.

Returns: A markdown block with vipLevel and the isMarginEnabled/isFutureEnabled/ isOptionsEnabled/isPortfolioMarginRetailEnabled flags, or raw JSON with response_format="json".

Examples: params = {}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_account_snapshotA

Return daily balance snapshots for the SPOT, MARGIN or FUTURES wallet.

Calls GET /sapi/v1/accountSnapshot (SIGNED, IP weight 2400 — a fifth of the 12000/min /sapi IP budget in a single call; call this sparingly, never in a tight loop). Binance only retains roughly the last month of snapshots and rejects windows of 30 days or more, so start_time/end_time are validated locally before the call to fail fast with a clear message.

When to Use:

  • To reconstruct a historical balance curve ("what was I holding a week ago").

  • As an occasional, deliberate call — not for polling the current balance.

When NOT to Use:

  • For the current live balance — use binance_get_spot_account (spot_account.py), which is far cheaper (IP weight 20) and reflects right now, not yesterday.

Returns: A markdown block per snapshot day (UTC date, totalAssetOfBtc, and a table of non-zero balances sorted largest-first, capped at 50 rows per day), or raw JSON with response_format="json".

Windows: start_time/end_time (int ms or ISO-8601) together must span less than 30 days; with only start_time given, end_time defaults to now and the same 30-day span check applies. Either way, start_time itself must be within the last 30 days — Binance does not retain snapshots older than that, regardless of window width. Omit both to get the most recent limit days. limit is 7-30 (Binance default 7).

Examples: params = {"type": "SPOT"} params = {"type": "SPOT", "start_time": "2026-09-01", "end_time": "2026-09-10", "limit": 10}

Error Handling: A window of 30 days or more, or a start_time more than 30 days ago, is rejected locally instead of round-tripping to Binance's "Support query within the last one month only". This endpoint answers HTTP 200 with {code, msg, snapshotVos} on failure (no success field, so the client's envelope check does not catch it) — a non-200 code is surfaced as an Error: here. -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_system_statusA

Report whether the Binance system is up or under maintenance.

Calls GET /sapi/v1/system/status (NONE — no key or signature needed, IP weight 1).

When to Use:

  • Before assuming a failure is account-specific — rule out a Binance-wide maintenance window first.

When NOT to Use:

  • To check THIS key's connectivity/permissions — use binance_health_check.

Returns: normal or maintenance plus Binance's message, or raw JSON with response_format="json".

Examples: params = {}

Error Handling: This endpoint needs no credentials at all; a failure here means Binance itself is unreachable, not a key or signature problem.

binance_get_delist_scheduleA

List symbols scheduled to be delisted, with their delisting date.

Calls GET /sapi/v1/spot/delist-schedule (API key only — no signature, IP weight 100). Useful to avoid opening new positions in a symbol about to stop trading.

When to Use:

  • Before placing a new order, to check the symbol is not on the delist schedule.

  • As a periodic sweep of open positions against upcoming delistings.

When NOT to Use:

  • To check whether a symbol is trading right now — use binance_get_exchange_info (market_data.py) and read its status field.

Returns: A markdown table of delist date → symbols, capped at 50 rows, or raw JSON with response_format="json".

Examples: params = {}

Error Handling: -2015 means the key is missing/invalid or this IP is not allowlisted (this endpoint only needs the X-MBX-APIKEY header, not a signature).

binance_get_funding_walletA

Read the Funding wallet — the wallet behind Binance Pay, Card and Gift Card.

Calls POST /sapi/v1/asset/get-funding-asset (SIGNED, IP weight 1). Binance uses POST for this query; it is on the client's read allowlist, so it works with the trading kill-switch off. Per Binance's own documentation this endpoint "supports querying: Binance Pay, Binance Card, Binance Gift Card, Stock Token" — i.e. it is the Funding wallet, and the closest thing to a card balance the API exposes.

When to Use:

  • To see what is sitting in Funding (Pay / Card / Gift Card / P2P proceeds).

  • Before a FUNDING_MAIN transfer, to check there is something to move.

When NOT to Use:

  • For Spot balances — use binance_get_user_assets here, or binance_get_spot_account (spot_account.py) for the full account view.

  • For a wallet-by-wallet total across Spot/Funding/Earn/Futures — use binance_get_wallet_balances.

  • To list Binance Card spending: that has no API endpoint at all. Card-funded Binance Pay payments show up in binance_get_pay_transactions (pay.py) with walletType 4/6; nothing else is retrievable.

Returns: A markdown table of asset / free / locked / freeze / withdrawing (plus a BTC valuation column and total when need_btc_valuation is set), capped at 50 rows, or the raw Binance array with response_format="json".

Examples: params = {} params = {"asset": "USDT"} params = {"need_btc_valuation": True, "response_format": "json"}

Error Handling: An empty list means the Funding wallet holds nothing (common — a Spot-only account never funds it). -2015 means the key lacks Reading permission or this IP is not allowlisted. A 404 means the base URL has no /sapi (the spot testnet).

binance_get_user_assetsA

List the Spot wallet's non-zero balances, optionally valued in BTC.

Calls POST /sapi/v3/asset/getUserAsset (SIGNED, IP weight 5). Another Binance query that uses POST; it is on the client's read allowlist and works with the trading kill-switch off. With no asset filter it returns every asset with a positive balance — unlike /api/v3/account, zero balances are omitted by Binance itself.

When to Use:

  • For a compact "what do I actually hold on Spot" answer, with a BTC valuation.

  • As the asset seed for binance_discover_traded_symbols (trade_history.py).

When NOT to Use:

  • For the full account view (permissions, commission rates, canTrade) — use binance_get_spot_account (spot_account.py).

  • For the Funding wallet — use binance_get_funding_wallet.

Returns: A markdown table of asset / free / locked / freeze / withdrawing / ipoable (plus BTC valuation and a total when need_btc_valuation is set), capped at 50 rows, or the raw Binance array with response_format="json".

Examples: params = {} params = {"asset": "BTC", "need_btc_valuation": True}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted. A 404 means the base URL has no /sapi (the spot testnet).

binance_get_wallet_balancesA

Show one total per wallet: Spot, Funding, Cross/Isolated Margin, Futures, Earn…

Calls GET /sapi/v1/asset/wallet/balance (SIGNED, IP weight 60 — 60 of the 12000/min /sapi IP budget, so it is fine occasionally but not in a poll loop). Binance returns one row per wallet with its total value in quote_asset and whether the wallet is activated.

When to Use:

  • First call when asking "where is my money" — it says which wallets hold anything before you spend weight listing assets wallet by wallet.

  • Before a transfer, to confirm the source wallet actually holds the balance.

When NOT to Use:

  • For per-asset detail — use binance_get_user_assets (Spot) or binance_get_funding_wallet (Funding).

  • For a daily history of balances — use binance_get_account_snapshot (wallet_account.py), which is far heavier (IP 2400).

Returns: A markdown table of wallet / activated / balance in the quote asset, plus the sum, or the raw Binance array with response_format="json".

Examples: params = {} params = {"quote_asset": "USDT"}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted. A 404 means the base URL has no /sapi (the spot testnet).

binance_get_transfer_historyA

List past transfers between the account's own wallets, one direction at a time.

Calls GET /sapi/v1/asset/transfer (SIGNED, IP weight 1). Unlike the POST that performs a transfer, this read does not need the key's "Permits Universal Transfer" flag.

type is mandatory and Binance offers no "all directions" value: MAIN_FUNDING and FUNDING_MAIN are two separate queries, so a full Spot⇄Funding picture costs two calls. MAIN_FUNDING / FUNDING_MAIN is also the closest proxy to a Binance Card top-up log, since the card was funded out of the Funding wallet.

When to Use:

  • To reconcile where a balance went between wallets.

  • To reconstruct Funding-wallet activity that Pay/fiat history does not explain.

When NOT to Use:

  • For deposits/withdrawals to and from other platforms — use binance_get_deposit_history / binance_get_withdraw_history (wallet_capital.py).

  • To perform a transfer — that is binance_transfer_between_wallets.

Returns: Binance's {total, rows} rendered as a markdown table of time / asset / amount / type / status / tranId, with the page position and the per-asset totals of the rows shown, or the raw envelope with response_format="json".

Pagination: page → Binance's current (1-based), limit → Binance's size (max 100, Binance default 10). total in the response is the full count for the filter, so page * limit < total means there is more.

Windows: Binance "supports query within the last 6 months only" and defaults to the last 7 days when start_time/end_time are omitted — so an empty result with no window given usually means "nothing in the last week", not "never". Pass start_time to look further back.

Examples: params = {"type": "MAIN_FUNDING"} params = {"type": "FUNDING_MAIN", "start_time": "2026-03-01", "limit": 100}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted. Dates more than 6 months old simply return nothing.

binance_get_dust_logA

List past dust-to-BNB conversions, with the per-asset detail of each one.

Calls GET /sapi/v1/asset/dribblet (SIGNED, IP weight 1). Binance returns "only the last 100 records" and "only records after 2020/12/01".

When to Use:

  • To find out what a past "convert small balances to BNB" actually converted, and what the service charge was.

  • To check whether an asset disappeared because it was swept as dust.

When NOT to Use:

  • To see what could be converted right now — use binance_get_dust_convertible.

  • To actually convert — that is binance_convert_dust_to_bnb.

Returns: One markdown section per conversion batch (time, transId, total transferred BNB, total service charge) followed by a table of the assets in that batch, or the raw envelope with response_format="json".

Windows: start_time/end_time are optional; Binance caps the history at the last 100 records regardless of the window, and keeps nothing before 2020-12-01.

Examples: params = {} params = {"start_time": "2026-01-01", "end_time": "2026-06-30"}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_dust_convertibleA

Preview which small balances can be converted to BNB, and what they are worth.

Calls POST /sapi/v1/asset/dust-btc (SIGNED, IP weight 1). Binance uses POST for this query; it is on the client's read allowlist, so the preview works even with the trading kill-switch off. Nothing is converted by this call.

When to Use:

  • Always, immediately before binance_convert_dust_to_bnb — it names the exact assets that are eligible and the BNB each one yields.

When NOT to Use:

  • To see conversions that already happened — use binance_get_dust_log.

Returns: A markdown table of asset / free amount / value in BTC / BNB you would receive (on-exchange and off-exchange rates when Binance sends both), plus the batch totals and the service-charge percentage, or the raw envelope with response_format="json".

Examples: params = {} params = {"account_type": "MARGIN"}

Error Handling: An empty details list means nothing currently qualifies as dust. -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_asset_detailA

Report per-asset deposit/withdraw status, withdraw fee and minimum.

Calls GET /sapi/v1/asset/assetDetail (SIGNED, IP weight 1). Binance answers with a map keyed by asset, not a list.

When to Use:

  • To check whether deposits or withdrawals are currently suspended for an asset.

  • To read an asset's withdraw fee and minimum before planning a movement elsewhere.

When NOT to Use:

  • For per-network detail (which chain, its own fee/min) — use binance_get_coin_config (wallet_capital.py).

  • To actually withdraw: this server has no withdrawal tool, by design, and the HTTP client refuses /sapi/v1/capital/withdraw/apply under every configuration.

Returns: A markdown table of asset / deposit / withdraw / withdraw fee / min withdraw / tip, capped at 50 assets (pass asset to narrow), or the raw map with response_format="json".

Examples: params = {"asset": "BTC"} params = {}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted. An unknown asset comes back as an empty map, not an error.

binance_get_trade_feesA

Report the maker/taker commission rates that apply to this account.

Calls GET /sapi/v1/asset/tradeFee (SIGNED, IP weight 1). Without symbol Binance returns every symbol — thousands of rows — so the rendering is capped at 50 and the JSON output is clipped; pass symbol whenever you know it.

When to Use:

  • To price a trade properly before placing it.

  • To confirm a VIP-tier or BNB-discount fee change took effect.

When NOT to Use:

  • For the fee actually charged on an executed order — that is in the order's fills (binance_place_order) or in binance_get_my_trades (trade_history.py).

  • For the account-level commission rates on one symbol with the order-book context — binance_get_commission_rates (spot_account.py) reads /api/v3/account/commission.

Returns: A markdown table of symbol / maker / taker as percentages, capped at 50 rows, or the raw Binance array with response_format="json".

Examples: params = {"symbol": "BTCUSDT"} params = {}

Error Handling: -1121 means the symbol does not exist. -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_asset_dividendsA

List asset distributions credited to the account (airdrops, rebates, interest).

Calls GET /sapi/v1/asset/assetDividend (SIGNED, IP weight 10). This is Binance's "asset dividend record": savings interest, BNB fee rebates, airdrops, referral payouts and similar credits, each with the reason in enInfo.

When to Use:

  • To explain a balance that grew without a trade or a deposit.

  • To total up rebates/airdrops over a period.

When NOT to Use:

  • For Simple Earn positions and their APR — use the earn tools (simple_earn.py).

  • For trades — use binance_get_my_trades (trade_history.py).

Returns: A markdown table of time / asset / amount / description / tranId, capped at 50 rows, plus per-asset totals of the rows shown, or the raw envelope with response_format="json".

Windows: start_time..end_time must span at most 180 days — Binance rejects anything wider, and this is checked locally before the call. Omit both for Binance's own default window.

Examples: params = {"asset": "BNB", "limit": 100} params = {"start_time": "2026-01-01", "end_time": "2026-06-01"}

Error Handling: A window wider than 180 days is rejected locally with an Error: naming the cap, instead of round-tripping to Binance. -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_transfer_between_walletsA

Move funds between the account's OWN wallets (Spot ⇄ Funding ⇄ Margin ⇄ Futures).

Calls POST /sapi/v1/asset/transfer (SIGNED, UID weight 300 of the 180000/min UID budget). The funds stay inside this Binance account: this is an internal move between wallets, never a transfer to another user and never a withdrawal off the platform. No tool in this server can send funds out of Binance.

Kill-switch. This call is refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1. The gate lives in the HTTP client, so no tool can bypass it. If you see that error, the operator has deliberately put the server in read-only mode — report it, do not try to work around it.

Key permission. The API key additionally needs the "Permits Universal Transfer" flag; without it Binance rejects the call even with the kill-switch on. binance_get_api_restrictions (wallet_account.py) reports it as permitsUniversalTransfer.

The isolated-margin directions need the pair named — from_symbol for ISOLATEDMARGIN_MARGIN and ISOLATEDMARGIN_ISOLATEDMARGIN, to_symbol for MARGIN_ISOLATEDMARGIN and ISOLATEDMARGIN_ISOLATEDMARGIN. Both rules are checked locally, so a malformed transfer fails before anything is signed or sent.

When to Use:

  • After a human has approved this specific movement of this specific amount.

  • To fund Binance Pay (MAIN_FUNDING) or to sweep Funding back to Spot (FUNDING_MAIN).

When NOT to Use:

  • To send crypto to another exchange or wallet — this server never withdraws.

  • To swap one asset for another — that is the convert tools (convert.py) or a spot order (binance_place_order).

  • To check what a past transfer did — use binance_get_transfer_history.

Returns: A confirmation echoing exactly what Binance returned, which is only the tranId. Binance sends no status field on this endpoint, so the confirmation says the transfer was accepted and points at binance_get_transfer_history / binance_get_wallet_balances to verify it settled. It never claims a balance changed.

Examples: params = {"type": "MAIN_FUNDING", "asset": "USDT", "amount": "25.5"} params = {"type": "FUNDING_MAIN", "asset": "BNB", "amount": "0.1"} params = {"type": "MARGIN_ISOLATEDMARGIN", "asset": "USDT", "amount": "100", "to_symbol": "BTCUSDT"}

Error Handling:

  • Error: … trading is disabled … → the kill-switch is off; nothing was sent.

  • -2015 / "permission denied" → the key lacks "Permits Universal Transfer", or this IP is not allowlisted.

  • -3020 / insufficient balance → the source wallet does not hold the amount.

  • A 5xx or a timeout means the transfer status is UNKNOWN — it may have gone through. Check binance_get_transfer_history for the same type before retrying; never resend blindly.

binance_convert_dust_to_bnbA

Convert small balances to BNB. Irreversible — the assets are sold for BNB.

Calls POST /sapi/v1/asset/dust (SIGNED, UID weight 10). Every asset listed is swapped to BNB at Binance's dust rate, minus a service charge; there is no undo and no "cancel" endpoint.

Preview first. Run binance_get_dust_convertible and pass only assets it listed: it names what qualifies and how much BNB each one yields, and it works even with the kill-switch off.

Kill-switch. This call is refused with Error: … trading is disabled … unless the server runs with BINANCE_ALLOW_TRADING=1. The gate lives in the HTTP client, so no tool can bypass it. If you see that error, the operator has deliberately put the server in read-only mode — report it, do not try to work around it.

Key permission. The API key needs "Enable Spot & Margin Trading"; this is a trade, not a transfer.

At most 100 assets per call — a client-side guard, not a Binance limit (Binance documents no cap). Split a longer list into batches; each batch is its own irreversible conversion.

When to Use:

  • After a human approved converting these specific assets, and after the preview confirmed they qualify.

When NOT to Use:

  • To swap a meaningful amount of one asset for another — the dust rate is worse than the market; use the convert tools (convert.py) or a spot order instead.

  • To see what happened in past conversions — use binance_get_dust_log.

Returns: A confirmation echoing exactly what Binance returned: totalTransfered (BNB received), totalServiceCharge, and the per-asset transferResult rows with their tranIds. Nothing is inferred; an asset Binance silently skipped simply will not appear in the table.

Examples: params = {"assets": ["ADA"]} params = {"assets": ["ADA", "DOT", "XRP"], "account_type": "SPOT"}

Error Handling:

  • Error: … trading is disabled … → the kill-switch is off; nothing was converted.

  • -2015 means the key lacks Spot & Margin Trading permission, or this IP is not allowlisted.

  • "The asset does not have a dust balance" family of errors → re-run binance_get_dust_convertible; eligibility changes with price.

  • A 5xx or a timeout means the conversion status is UNKNOWN — check binance_get_dust_log before retrying; a duplicate conversion cannot be undone.

binance_get_deposit_historyA

List crypto deposits into the account for one window (up to 90 days).

Calls GET /sapi/v1/capital/deposit/hisrec (SIGNED, IP weight 1). One call answers a single window; Binance caps that window at "less than 90 days" and defaults to the last 90 days when no times are given. The cap is enforced here, before the request, so an over-wide window fails with a readable message instead of -1127.

When to Use:

  • "Did my USDT deposit land?" — a recent, bounded lookup.

  • Reconciling one month's deposits, or chasing one tx_id.

When NOT to Use:

  • For the full history since the account opened — use binance_get_all_deposits, which walks these windows for you and returns a resume cursor.

  • For withdrawals — use binance_get_withdraw_history.

  • For fiat (card/bank) deposits — those are not here; use binance_get_fiat_orders (fiat.py).

Returns: A markdown table (insertTime, completeTime, coin, amount, network, status, walletType, txId) plus per-coin totals, capped at 50 displayed rows; or the raw Binance array with response_format="json".

Pagination: limit is 1-1000 (Binance default 1000) and offset pages within the window. A full page means there is more: re-call with offset += limit.

Windows: start_time/end_time together must span under 90 days. start_time alone must be under 90 days ago (Binance defaults endTime to now). end_time alone gets a startTime of end_time - 89 days so the window actually brackets it.

Examples: params = {"coin": "USDT", "status": "success"} params = {"start_time": "2026-08-01", "end_time": "2026-09-01"} params = {"tx_id": "0xabc...", "response_format": "json"}

Error Handling: An over-wide window is rejected locally. -2015 means the key lacks Reading permission or this IP is not allowlisted. /sapi does not exist on the spot testnet — a 404 there is expected.

binance_get_withdraw_historyA

List crypto withdrawals out of the account for one window (up to 90 days).

Calls GET /sapi/v1/capital/withdraw/history (SIGNED). This is a read — this server can never submit a withdrawal: POST /sapi/v1/capital/withdraw/apply is on the client's forbidden-path list and no tool exists for it.

⚠️ Cost: UID weight 18000 per call (a tenth of the 180000/min per-account budget) and a hard limit of 10 requests per second on this endpoint — Binance reports the per-second usage in X-SAPI-USED-UID-WEIGHT-1S. Do not poll it.

Each row includes transactionFee, the network fee Binance charged for that withdrawal, so the true cost of moving funds out is readable here.

When to Use:

  • "Did my withdrawal go through, and what did it cost?" — a recent, bounded lookup.

  • Looking up specific withdrawals by withdraw_order_id or id_list.

When NOT to Use:

  • For the full history since the account opened — use binance_get_all_withdrawals, which budgets these expensive calls for you.

  • For deposits — use binance_get_deposit_history.

  • To MAKE a withdrawal — impossible by design; use the Binance app.

Returns: A markdown table (applyTime, completeTime, coin, amount, transactionFee, network, status, walletType, txId, withdrawOrderId) plus per-coin totals including fees, capped at 50 displayed rows; or the raw Binance array with response_format="json".

Pagination: limit is 1-1000 (Binance default 1000) and offset pages within the window. id_list accepts at most 45 ids and is sent comma-separated.

Windows: start_time/end_time together must span under 90 days — under 7 days when withdraw_order_id is set (Binance's own rule; it also defaults to the last 7 days in that case). Both caps are enforced locally.

Examples: params = {"coin": "BTC", "status": "completed"} params = {"start_time": "2026-08-01", "end_time": "2026-09-01"} params = {"id_list": ["b6ae22b3aa844210a7041aee7589627c"], "response_format": "json"}

Error Handling: An over-wide window is rejected locally. -2015 means the key lacks Reading permission or this IP is not allowlisted. A 429 here means the 10 req/s ceiling was hit — back off, do not retry in a loop.

binance_get_all_depositsA

Every crypto deposit since since — the 90-day cap walked for you.

Binance only answers 90 days at a time, so this walks untilsince in 89-day windows, newest first, paging offset by 1000 inside each window until a short page proves it is drained. Rows are deduped by their Binance id, so overlapping windows (and a resumed run) can never double-count.

since defaults to 2017-07-01, Binance's launch: there is no API that reports when an account was created — apiRestrictions.createTime is the API KEY's date, not the account's — so "everything" means "since the exchange existed". Windows before the account opened simply return nothing.

Cost: GET /sapi/v1/capital/deposit/hisrec is IP weight 1, so the default max_calls=60 (≈ 15 years of windows) is cheap. The budget is checked BEFORE every request and the reported call count is the real one.

When to Use:

  • "Show me every deposit I have ever made" — the headline question.

  • Reconstructing cost basis or an audit trail of money coming IN.

When NOT to Use:

  • For one recent window — binance_get_deposit_history is one call.

  • For withdrawals — use binance_get_all_withdrawals.

  • For fiat on-ramps (card/bank) — use binance_get_fiat_orders / binance_get_fiat_payments (fiat.py); they are a different rail.

Returns: Rows sorted newest-first with per-coin totals (count + summed amount). Markdown displays at most 50 rows; response_format="json" returns {count, truncated, no_progress, since, until, resume_before, calls_made, totals, items} with the full set. truncated is true exactly when the walk did not reach since; no_progress is true when it did not finish even the first window, and then resume_before is null on purpose — see Pagination.

Pagination: If the walk stops before since — budget exhausted, or an error — it returns the rows it already has PLUS resume_before, the boundary of the next UNFETCHED range. Call again with the same since and that resume_before to continue. A stop in the middle of a window re-fetches that window, which the dedupe makes harmless. If it stopped without completing even the FIRST window there is no cursor to give: resume_before comes back null with no_progress: true, because repeating the run with resume_before = until would re-issue the identical calls forever. Raise max_calls (or fix the error) and re-run the same range instead.

Examples: params = {} params = {"since": "2024-01-01", "coin": "USDT"} params = {"since": "2017-07-01", "resume_before": 1717200000000, "response_format": "json"}

Error Handling: An over-wide-window error from Binance is tolerated: the window is halved and retried. Anything else — auth (-2015), rate limits (429/418), a Binance envelope failure — stops the walk immediately and is reported alongside the rows already collected and the resume cursor, so nothing fetched is ever thrown away.

binance_get_all_withdrawalsA

Every crypto withdrawal since since — the 90-day cap walked for you.

Same walk as binance_get_all_deposits (89-day windows newest-first, offset paging by 1000 inside each, dedupe by Binance id), against GET /sapi/v1/capital/withdraw/history. Reading only — this server can never submit a withdrawal.

⚠️ Each call costs UID weight 18000 of the 180000/min per-account budget, and the endpoint separately allows only 10 requests per second. That is why max_calls defaults to 10 — one full minute of UID budget — instead of the 60 the deposit walk uses. A full 2017→today sweep needs ~35 windows, so expect to resume across several calls; the cursor makes that exact and gap-free.

since defaults to 2017-07-01, Binance's launch: no API reports an account's creation date (apiRestrictions.createTime is the API KEY's date).

When to Use:

  • "Show me every withdrawal I have ever made", including the fees they cost.

  • Auditing money going OUT, for tax or reconciliation.

When NOT to Use:

  • For one recent window — binance_get_withdraw_history is one call.

  • For deposits — use binance_get_all_deposits.

  • To MAKE a withdrawal — impossible by design.

Returns: Rows sorted newest-first with per-coin totals (count, summed amount, summed transactionFee). Markdown displays at most 50 rows; response_format="json" returns {count, truncated, no_progress, since, until, resume_before, calls_made, totals, items} with the full set. truncated is true exactly when the walk did not reach since; no_progress is true when it did not finish even the first window, and then resume_before is null on purpose — see Pagination.

Pagination: If the walk stops before since — which with max_calls=10 is the normal case for a multi-year sweep — it returns the rows it has PLUS resume_before, the boundary of the next UNFETCHED range. Call again with the same since and that resume_before; repeat until truncated is false. If not even the first window completed, resume_before is null and no_progress is true: raise max_calls and re-run the same range, since resuming at until would repeat the identical calls.

Examples: params = {} params = {"since": "2024-01-01", "coin": "BTC"} params = {"since": "2017-07-01", "resume_before": 1717200000000, "max_calls": 10}

Error Handling: An over-wide-window error is tolerated (the window is halved and retried). Auth (-2015), rate limits (429/418) and envelope failures stop the walk immediately and are reported alongside the rows already collected and the resume cursor.

binance_get_deposit_addressA

Get the deposit address for one coin on one network.

Calls GET /sapi/v1/capital/deposit/address (SIGNED, IP weight 10). Omitting network returns the coin's default network — which is NOT always the one you want; binance_get_coin_config lists every network with its isDefault flag.

⚠️ Sending a coin to an address on the wrong network loses the funds. Confirm the network before using the address, and use the tag/memo when one is returned.

When to Use:

  • Before sending crypto into Binance from an external wallet.

When NOT to Use:

  • To see every address already issued for a coin — use binance_get_deposit_addresses.

  • To check whether deposits are even enabled for that coin/network right now — use binance_get_coin_config first.

Returns: A markdown block with address, coin, tag and Binance's url (a block-explorer link), or raw JSON with response_format="json".

Examples: params = {"coin": "USDT", "network": "TRX"} params = {"coin": "BTC"}

Error Handling: An unknown coin/network pair returns a Binance error naming the parameter. -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_deposit_addressesA

List every deposit address issued for one coin, across networks.

Calls GET /sapi/v1/capital/deposit/address/list (SIGNED, IP weight 10) and marks which address is the default for its network.

When to Use:

  • To recognise an address you have used before, or to audit which addresses belong to this account.

When NOT to Use:

  • To get an address to deposit to right now — binance_get_deposit_address returns the canonical one for a coin/network pair.

Returns: A markdown table of network, address, tag and isDefault, capped at 50 rows, or raw JSON with response_format="json".

Examples: params = {"coin": "USDT"} params = {"coin": "USDT", "network": "BSC"}

Error Handling: -2015 means the key lacks Reading permission or this IP is not allowlisted.

binance_get_coin_configA

Per-coin deposit/withdraw switches, networks, fees and minimums.

Calls GET /sapi/v1/capital/config/getall (SIGNED, IP weight 10). The endpoint takes no filter and returns every listed coin (hundreds), so coin is applied client-side after the call — the cost is the same either way, which is why it is worth calling once and reading several coins out of the JSON.

This is where you learn, before moving anything: whether deposits/withdrawals are enabled at all for a coin, which networks it supports, which is the default, what each network charges (withdrawFee) and its minimum (withdrawMin).

When to Use:

  • Before depositing — confirm depositEnable on the network you plan to use.

  • To compare network fees for the same asset (e.g. USDT on TRX vs ETH).

When NOT to Use:

  • To get the actual address — use binance_get_deposit_address.

  • For trading fees — that is binance_get_trade_fees (wallet_asset.py); this is the on-chain transfer fee.

Returns: Per coin: depositAllEnable / withdrawAllEnable, then a per-network table of isDefault, depositEnable, withdrawEnable, withdrawFee and withdrawMin. Capped at 50 coins in markdown (pass coin to narrow); response_format="json" returns the filtered payload in full.

Examples: params = {"coin": "USDT"} params = {"response_format": "json"}

Error Handling: An unknown coin returns an empty result, not an error — the filter is local. -2015 means the key lacks Reading permission or this IP is not allowlisted.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.6/5.0

Scored across 83 tools

Disambiguation5/5

Each of the 83 tools targets a distinct resource+action pairing (e.g., ticker_price vs book_ticker vs ticker_24h vs rolling_ticker vs trading_day_ticker), and the genuinely confusable clusters are separated by explicit cross-references. The 'When NOT to Use' sections consistently name the alternative tool, so an agent can reliably disambiguate even dense groups like the six account-status/wallet tools or the deposit_history/all_deposits pair.

Naming Consistency5/5

Every tool follows the uniform binance_<verb>_<noun> snake_case convention: binance_get_* for all reads, binance_place_*/binance_cancel_*/binance_accept_* for mutations, with compound verbs like cancel_replace and convert_dust_to_bnb. The only deviations (health_check vs check_health, all_my_trades vs my_trades) are negligible and do not break the pattern.

Tool Count2/5

83 tools is far beyond the 25+ threshold for an overloaded surface, even though the scope (the full Binance spot API) is genuinely broad and every tool maps to a distinct endpoint. The volume will strain agent context windows and slow tool selection; this surface would be easier to navigate split into market-data, trading, and wallet/capital servers.

Completeness5/5

The surface covers market data, the full spot order lifecycle (test/place/cancel/replace/cancel-all), all three order-list types, convert with quote-accept-limit lifecycle, TWAP algo orders, fiat/pay/earn, wallets, transfers, dust, and capital history — each with single-window and budgeted-walk variants. Every mutation has a documented verification path for UNKNOWN states, and the only omissions (withdrawal creation, futures/margin) are deliberate, explicitly stated design boundaries.

Maintenance

ActivityMaintained
ResponsivenessNo issues