> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xmonaco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# V1.0.37

# Monaco Protocol SDK v1.0.37

This is an additive release — no breaking changes. It adds a **post-only** flag to limit-order placement and replacement across every client. `postOnly` is a maker-only guarantee, not a new order type: a placement or replacement that would cross the book is rejected instead of matching, so a resting quote never accidentally takes. Existing code keeps working unchanged; the flag is opt-in. The one thing to know before adopting it is how a crossing rejection surfaces — a message match for single orders, a structured error code for batches.

## Added

### Post-only orders

Set `postOnly: true` alongside a normal limit placement or replacement to guarantee the order can only add liquidity. If the price would cross the book at admission time (`BUY` at or above the best ask, or `SELL` at or below the best bid), Monaco rejects the order instead of letting it take.

* Exposed on every limit-order surface: `sdk.trading.placeLimitOrder`, `replaceOrder`, `batchCreate`, and `batchReplace` (`@0xmonaco/core`), the `useTrade()` equivalents (`@0xmonaco/react`), and the REST `create_order` / `batch_create_orders` / `replace_order` / `batch_replace_orders` endpoints (`POST /api/v1/orders`, `POST /api/v1/orders/batch-create`, `PUT /api/v1/orders/{order_id}`, `POST /api/v1/orders/batch-replace`) and their gRPC `OrdersService` equivalents. The MCP `place_limit_order` and `replace_order` tools take an optional `postOnly` too.
* **Maker-only, not a new order type.** `postOnly` composes with `LIMIT` orders using `GTC` time in force only. It is rejected on `MARKET` orders and rejected when combined with `IOC` or `FOK` — both are immediate-or-cancel semantics that contradict a maker-only guarantee. It is not available on `placeMarketOrder`. The TypeScript schemas enforce these combinations client-side on `placeLimitOrder` and `batchCreate` so a bad combination fails fast without a round trip — but that client check is for fast feedback only; the server's own validation is authoritative and always enforced.
* **Crossing rejection.** A crossing `postOnly` order or replacement is rejected with REST `400 Bad Request` / gRPC `InvalidArgument`, message containing `"post-only order would cross"` (internally logged as `POST_ONLY_WOULD_CROSS`). For a single `placeLimitOrder` or `replaceOrder`, that code is **not** part of the response body — match on the message text. `batchCreate` and `batchReplace` are different: each per-item result carries a structured `error.code`, set to `POST_ONLY_WOULD_CROSS` for a post-only crossing rejection — match on `code` there.
* **Replace semantics.** `postOnly` is re-stated explicitly on every replacement; it is never inherited from the original order. A single `replaceOrder` validates `postOnly` *before* cancelling the original, so a rejected replacement leaves the original resting, untouched. `batchReplace` is cancel-first: a batch item whose `postOnly` replacement is rejected for crossing reports the error with its original **already cancelled**, matching the existing failed-to-place batch-replace contract — refresh your live orders before retrying.
* **Admission-time check only.** The crossing predicate is evaluated once, when the order is admitted (placed or replaced) — `postOnly` is not a perpetual anti-taker guarantee. Once a non-crossing `postOnly` order is admitted and rests, it behaves like an ordinary resting order of the same time in force: a later book move can trade against it like any other resting order. The flag is not stored on the order and not echoed back in order-detail responses.

See [Post-Only Orders](/developers/trade#post-only-orders) for the full crossing predicate and the replace / batch-replace resting-order contract.

<Warning>
  **Corrections since this release.** The original wording is left in place above; three statements have been superseded:

  * *"The flag is not stored on the order and not echoed back in order-detail responses"* — false since v1.0.38: `postOnly` is persisted on the order and returned on order detail and list responses, and since v1.0.51 it is also echoed on the order WebSocket events (the placement acknowledgement, taker fills, cancellations, and expiry). Absent means not post-only; the key is never sent as `false`.
  * *"For a single `placeLimitOrder` or `replaceOrder`, that code is **not** part of the response body — match on the message text"* — superseded in v1.0.38: a crossing rejection now carries the stable error code `POST_ONLY_WOULD_CROSS` on every surface (the REST error envelope's `code` field, the gRPC `google.rpc.ErrorInfo` reason, and the batch per-item `error.code`). Matching the message substring still works but is a legacy fallback.
  * *"a batch item whose `postOnly` replacement is rejected for crossing reports the error with its original **already cancelled**"* — superseded in v1.0.47: the crossing check now runs in the pre-cancel preflight, evaluated against the book as it will stand once the batch's own cancels are applied, so a refused item ordinarily leaves its original resting with the same order ID and queue position. See [Batch Replace](/developers/trade#batch-replace) for the narrow cases where the original is still lost.
</Warning>

## Upgrade

```bash theme={null}
npm install @0xmonaco/core@1.0.37 @0xmonaco/types@1.0.37 @0xmonaco/react@1.0.37 @0xmonaco/contracts@1.0.37
# or bun
bun add @0xmonaco/core@1.0.37 @0xmonaco/types@1.0.37 @0xmonaco/react@1.0.37 @0xmonaco/contracts@1.0.37
```

The MCP server ships at `1.0.37` too; it runs via `npx -y @0xmonaco/mcp-server`, so restarting your assistant picks up the new version and the `postOnly` tool inputs.

Nothing in this release is breaking. One thing worth adopting:

1. **Use `postOnly` for maker quoting.** Set `postOnly: true` on limit placements and replacements where an accidental take is worse than a rejected order you can immediately re-price — market-maker quoting, or rebuilding quotes right after a market reopens. Handle the crossing rejection by the message for single orders (`"post-only order would cross"`) and by `error.code === "POST_ONLY_WOULD_CROSS"` for batches, and remember `batchReplace` cancels first — a rejected item leaves no resting order behind.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.