Skip to content

Learn

Exchange APIs

What is a post-only order?

Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.

A post-only order is a limit order the venue will accept only if it rests on the order book; if any part of it would execute immediately against a resting order, the venue refuses it instead of filling it as a taker.

It exists for one reason: to make the maker/taker outcome a condition you set rather than a consequence of where the market happens to be when your order arrives. This page explains the mechanism, what the refusal looks like, how it differs from a plain limit order and from immediate-or-cancel, and how to handle it in code without turning a fee decision into an execution mistake.

Why this matters now

The fee gap between making and taking is covered in maker vs taker fees. The part that catches automated setups is quieter: a plain limit order does not know whether it will be a maker. It is priced when you compute it and evaluated when it arrives. If the market has moved to or through your price in between, the “limit order” executes on arrival and pays the taker fee. Nothing errors. The fill report is the first place you find out.

For a strategy whose margin depends on maker fees — or on maker rebates, which some venues pay; Hyperliquid documents them, paid per trade to the trading wallet — this silent conversion is a cost leak. Post-only closes it by making the venue refuse instead.

How it actually works

  1. You send a limit order marked post-only. Depending on the venue it may be a flag, a separate order type, or a time-in-force value; check the order endpoint documentation.
  2. The venue compares your price to the opposite side of the book at arrival — not at the time you computed it. A buy at or above the best ask, or a sell at or below the best bid, would match.
  3. If it would match, it is refused. Hyperliquid’s documented refusal is: Post only order would have immediately matched, bbo was {bbo}. — the message includes the best bid and offer at the moment of refusal. Its historical order status is badAloPxRejected.
  4. If it would not match, it rests as an ordinary limit order. From then on, if it is filled, it is filled as a maker.

CCXT’s unified hierarchy has a class for this situation, OrderImmediatelyFillable, under InvalidOrder and therefore under ExchangeError — “the exchange understood and refused”. Whether a given venue’s refusal is mapped to that class depends on CCXT’s per-exchange mapping, so check it before relying on it; see CCXT’s common errors.

Post-only vs the adjacent things

OrderIf it would match on arrivalIf it would not match
Plain limitExecutes as takerRests as maker
Limit + post-onlyRefusedRests as maker
Limit + IOCExecutes what it can as takerCancelled — nothing rests
Limit + FOKExecutes fully as taker, or not at allCancelled

Post-only and IOC are mirror images. IOC says only take, never rest; post-only says only rest, never take. A plain limit order is the one that does either, depending on timing you do not control.

The other confusion is post-only versus “a limit order priced away from the market”. Pricing away makes a maker outcome likely. Post-only makes it certain — or makes the order not exist.

The refusal is an outcome, not an error

The rejection rate of post-only orders is not constant. It rises when price is moving quickly towards your level, because that is when your computed price is most likely to be through the book by the time the order lands. A quoting strategy sees its rejections cluster in exactly the moments it most wanted to be in the market.

That makes the refusal informative. It tells you the market is currently at or through your price. What you do next is a strategy decision, and there are only three honest options:

  • Re-price behind the new best and try again, with a cap on attempts. Hyperliquid putting the current best bid and offer into the message is useful here.
  • Give up on this entry. If the setup required a maker fill at this level, and the market has moved through it, the setup has changed.
  • Accept taker execution deliberately by sending a different order — which is a new decision about fees and price, not a retry.

The option to avoid is the automatic one: a loop that re-sends the same post-only order unchanged (it will be refused again if price has not moved back), or a handler that “fixes” the refusal by dropping the flag. The first burns rate limit. The second converts a cost preference into a market order without anyone deciding that.

Where post-only does not belong

Exits you need to happen. A protective stop or an emergency close should prioritise execution; a post-only exit can be refused at exactly the moment price is moving against you. See order types explained for why protective exits should guarantee execution rather than price.

Anything a model drafts and then “repairs”. A model that sees a post-only refusal as a tool error will often try to resolve it — reprice aggressively, remove the flag, switch to market. Each of those changes the trade. If orders go through an approval step, a change of order type or removal of post-only should count as a new plan requiring a new approval, not as a retry of the approved one.

Where the boundary should sit

  • Use post-only on entries and quotes where the fee outcome is part of the reason for the trade.
  • Handle the refusal explicitly, with a written policy: re-price with a limit on attempts, or abandon.
  • Never let the refusal path escalate to a taker order automatically.
  • Log refusals with the book at the time. A refusal rate that climbs over weeks says something about your pricing logic or latency, and you will only see it if you record it.

FAQ

What happens when a post-only order would fill immediately?

The venue refuses it instead of executing it as a taker. Nothing trades and no taker fee is charged. How the refusal is reported varies by venue; Hyperliquid returns the message “Post only order would have immediately matched” together with the best bid and offer at the time.

Is a post-only order the same as a limit order?

It is a limit order with an extra condition. A plain limit order that would match on arrival executes as a taker; a post-only limit order in the same situation is refused. If it does not match on arrival, the two behave identically and rest on the book as makers.

Why are my post-only orders rejected so often?

Usually because your price is at or through the opposite best by the time the order arrives — either because it was priced at the touch, or because the market moved during the delay between computing the price and the order landing. Rejections cluster in fast markets. Pricing one or more ticks behind the best, and reducing latency, both lower the rate.

Should I use post-only on a stop-loss?

No. A stop-loss exists to get you out, and post-only can refuse the exit at the moment the market is moving against you. Protective exits should prioritise execution over fees; accept the taker fee on the way out.