July 16, 2026

Binance Order Types and Execution - Spot vs Futures

TL;DR

Binance Spot and USDⓈ-M Futures expose deliberately different order-placement models, and the differences cause most integration bugs. The two that bite hardest: maker-only (post-only) is an order type on Spot (LIMIT_MAKER) but a time-in-force value on Futures (GTX, Good-Till-Crossing), and iceberg orders exist on Spot (icebergQty) but not on USDⓈ-M Futures. An unexpected EXPIRED_IN_MATCH status is self-trade prevention (STP), not a bug. Because the two venues use different enums, filters, and rejection codes, teams integrating both typically normalize them behind a single order model instead of branching everywhere.

Why Spot and Futures diverge

Spot and USDⓈ-M Futures are separate API surfaces (/api/v3 for Spot, /fapi/v1 for Futures) with separate enum, filter, and error-code definitions. The docs describe how to place an order on each, but rarely put the two side by side, so the divergences stay hidden until an order behaves differently than the Spot code that "worked."

Post-only / maker-only: order type vs time-in-force

The single most common cross-venue trip-up.

  • Spot: maker-only is a dedicated order type, LIMIT_MAKER (a post-only type).
  • USDⓈ-M Futures: there is no LIMIT_MAKER; post-only is expressed as time-in-force GTX (Good-Till-Crossing) on a LIMIT order.

Spot post-only code cannot be reused on Futures by changing the symbol — the parameter that carries the intent moves from type to timeInForce.

Iceberg orders

  • Spot: supported via the icebergQty parameter on limit orders; the ICEBERG_PARTS and MAX_NUM_ICEBERG_ORDERS filters bound its behavior.
  • USDⓈ-M Futures: no native iceberg parameter — the Futures New Order request has no icebergQty, and Futures has no iceberg-related filters. Iceberg-like behavior is achieved by slicing client-side.

Time-in-force

  • Spot: exactly three — GTC, IOC, FOK.
  • USDⓈ-M Futures: six — GTC, IOC, FOK, GTX (post-only), GTD (good-till-date), and RPI (Retail Price Improvement, a post-only variant that only matches against App/Web orders).

Two divergences follow: GTX and GTD exist only on Futures. A Futures GTD order requires goodTillDate, which must be at least 600 seconds in the future.

Self-trade prevention (STP) and EXPIRED_IN_MATCH

STP is the usual explanation for orders that expire without an obvious cause.

  • Spot STP modes: NONE, EXPIRE_MAKER, EXPIRE_TAKER, EXPIRE_BOTH, DECREMENT, TRANSFER.
  • Futures STP modes: EXPIRE_TAKER, EXPIRE_MAKER, EXPIRE_BOTH — three, defaulting to EXPIRE_MAKER. Spot exposes more modes (including DECREMENT and TRANSFER) than Futures.
  • When STP prevents a self-match, the affected order gets status EXPIRED_IN_MATCH on both venues — not CANCELED / EXPIRED. Integrations that only handle CANCELED / EXPIRED / REJECTED will mishandle it.
  • On Futures, STP is only effective when timeInForce is IOC, GTC, or GTD.

Order status and execution-type enums

  • Spot statuses: NEW, PENDING_NEW, PARTIALLY_FILLED, FILLED, CANCELED, PENDING_CANCEL (currently unused), REJECTED, EXPIRED, EXPIRED_IN_MATCH.
  • Futures statuses: NEW, PARTIALLY_FILLED, FILLED, CANCELED, REJECTED, EXPIRED, EXPIRED_IN_MATCH — no PENDING_NEW or PENDING_CANCEL.
  • Spot execution types (on the stream): NEW, CANCELED, REPLACED, REJECTED, TRADE, EXPIRED, and TRADE_PREVENTION (expired due to STP).

Rate limits and request weights

  • Spot returns used weight in X-MBX-USED-WEIGHT-(intervalNum)(intervalLetter) (e.g. X-MBX-USED-WEIGHT-1M) and order counts in X-MBX-ORDER-COUNT-(intervalNum)(intervalLetter).
  • Exceeding a limit returns HTTP 429; continuing after a 429 escalates to an automated IP ban (HTTP 418), scaling from 2 minutes to 3 days. A Retry-After header gives the wait in seconds.
  • Placing an order on Futures counts differently: the Futures New Order endpoint is weight 0 on the IP limit but counts 1 against each order-count window (X-MBX-ORDER-COUNT-10S and X-MBX-ORDER-COUNT-1M). Futures order throughput is bounded by order-count, not IP weight.

Symbol reference and filters

  • The reference endpoint is exchangeInfo on both (/api/v3/exchangeInfo, /fapi/v1/exchangeInfo).
  • Order validity is governed by per-symbol filters, and the sets differ:
    • Spot: PRICE_FILTER, PERCENT_PRICE, PERCENT_PRICE_BY_SIDE, LOT_SIZE, MIN_NOTIONAL, NOTIONAL, ICEBERG_PARTS, MARKET_LOT_SIZE, MAX_NUM_ORDERS, MAX_NUM_ALGO_ORDERS, MAX_NUM_ICEBERG_ORDERS, MAX_POSITION, TRAILING_DELTA, and more.
    • Futures: PRICE_FILTER, LOT_SIZE, MARKET_LOT_SIZE, MAX_NUM_ORDERS, MAX_NUM_ALGO_ORDERS, PERCENT_PRICE, MIN_NOTIONAL.
  • Same-named filters can differ: Spot PERCENT_PRICEis evaluated against an average of previous trade prices; Futures PERCENT_PRICEis evaluated against the mark price. Futures MIN_NOTIONAL is a single notional floor (docs show 5.0); Spot splits this into MIN_NOTIONAL and a NOTIONAL (min + max) filter.
  • On Futures, a filter violation surfaces as a 40xx code — 4013 (price below min), 4014 (price not on tick size), 4164 (notional below MIN_NOTIONAL), 4131 (price outside PERCENT_PRICE).

Futures-only parameters and rejections

No Spot equivalent, and a frequent source of "unknown parameter" or logic errors when Spot code is ported:

  • positionSide (BOTH in One-way Mode; LONG / SHORT in Hedge Mode, where it is mandatory),
  • reduceOnly (cannot be sent in Hedge Mode),
  • priceMatch (OPPONENT / OPPONENT_5 / OPPONENT_10 / OPPONENT_20, QUEUE / QUEUE_5 / QUEUE_10 / QUEUE_20),
  • workingType (MARK_PRICE vs CONTRACT_PRICE) and closePosition, which apply to conditional orders.

Common Futures rejections: -2021 (order would immediately trigger) and -2022 (reduce-only rejected).

Recent gotcha — conditional orders moved to the Algo service. Since 2025-12-09, USDⓈ-M Futures conditional types (STOP, STOP_MARKET, TAKE_PROFIT, TAKE_PROFIT_MARKET, TRAILING_STOP_MARKET) are handled by the Algo Order endpoints. Sending them to the plain New Order endpoint returns -4120 (STOP_ORDER_SWITCH_ALGO); that endpoint now effectively accepts LIMIT and MARKET.

Spot vs Futures — at a glance

BehaviorSpot (/api/v3)USDⓈ-M Futures (/fapi/v1)
Maker-only / post-onlyOrder type LIMIT_MAKERTime-in-force GTX
IcebergicebergQty paramNot supported (slice client-side)
Time-in-force setGTC, IOC, FOKGTC, IOC, FOK, GTX, GTD, RPI
Stop / take-profit type namesSTOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMITSTOP, STOP_MARKET, TAKE_PROFIT, TAKE_PROFIT_MARKET, TRAILING_STOP_MARKET
Conditional ordersSame endpointAlgo endpoints (else -4120)
STP modesNONE, EXPIRE_MAKER, EXPIRE_TAKER, EXPIRE_BOTH, DECREMENT, TRANSFEREXPIRE_TAKER, EXPIRE_MAKER, EXPIRE_BOTH (default EXPIRE_MAKER)
Self-match statusEXPIRED_IN_MATCHEXPIRED_IN_MATCH
Extra order statusesPENDING_NEW, PENDING_CANCEL
Position side paramn/apositionSide (Hedge Mode)
Reduce-only / close-positionn/areduceOnly, closePosition
PERCENT_PRICE basisavg of previous trade pricesmark price
Order-placement rate accountingIP weight + order-count 0 on IP; counts X-MBX-ORDER-COUNT-10S / 1M
Filter-violation error codesfilter-specific-40xx (-4013 / -4014 / -4164 / -4131)
Symbol referenceexchangeInfoexchangeInfo

What this looks like through a normalization layer

When a desk trades both venues (and others besides), this branching multiplies. A connectivity/normalization layer sits beneath the execution system (OMS/EMS/algos) and presents one order model, so the caller expresses "post-only limit" once instead of choosing LIMIT_MAKER on Spot and timeInForce=GTX on Futures, and reads one canonical order state instead of reconciling EXPIRED_IN_MATCH against each venue's status set.

Axon Trade is one such layer. It uses a canonical slash-format symbol (e.g. ETH/USDT), identical for market data and execution across 30+ exchanges, reached through a single, slightly modified FIX 4.4 session rather than a per-venue REST/WebSocket integration. Its normalized reference data is delivered over FIX SecurityList (35=y) with Symbol (55) and SecurityExchange (207).

FAQ

How do you place a post-only order on Binance Futures?

On USD-M Futures post-only is set through time-in-force GTX on a limit order not through a separate order type.

Why is there no LIMIT_MAKER on Binance Futures?

Futures expresses maker-only through the GTX time-in-force instead of a LIMIT_MAKER order type which is a Spot only order type.

What does EXPIRED_IN_MATCH mean on Binance?

It means an order was expired by self-trade prevention because it would have matched an order from the same account or trade group rather than filled or canceled normally.

Does Binance Futures support iceberg orders?

No native iceberg parameter exists on USD-M Futures while Spot supports iceberg through the icebergQty parameter.

Which time-in-force values does Binance Spot support?

Binance Spot supports exactly GTC IOC and FOK while USD-M Futures adds GTX GTD and RPI.

Why did my Binance Futures stop order start returning -4120?

Since 2025-12-09 conditional order types moved to the Algo Order endpoints and the plain New Order endpoint rejects them with code -4120.

Sources

  • Binance Spot — General REST API Information, ENUM Definitions
  • Binance USDⓈ-M Futures — New Order, Common Definition, Error Code
  • Binance Derivatives — Change Log (conditional-order migration)
  • Facts verified against live docs as of July 2026; specific strings should be re-checked before reuse.

About Axon Trade

Axon Trade provides advanced trading infrastructure for institutional and professional traders, offering high-performance FIX API connectivity, real-time market data, and smart order execution solutions. With a focus on low-latency trading and risk-aware decision-making, Axon Trade enables seamless access to multiple digital asset exchanges through a unified API.

Explore Axon Trade’s solutions:

Contact Us for more info.