> ## 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.

# Batch replace orders

> Batch replace orders.

 Replace multiple orders in one engine step with per-item results: every
 original is cancelled first, then each replacement is placed in request
 order. A
 two-sided quote can therefore shift across its own resting prices in one
 call, and a replacement may use funds freed by any original in the batch.

 Failure semantics: an item that fails validation, or whose original
 cannot be found, leaves the original resting. An item whose replacement
 fails to PLACE (for example insufficient balance or self-trade
 prevention) reports the error with its original already cancelled.

 POST_ONLY_WOULD_CROSS is the exception: a post-only replacement that
 would cross is refused BEFORE the cancel pass, against the book as it
 will stand once the batch's own cancels are applied, so the item
 normally reports the error with its original still resting. It is not a
 guarantee — the pre-cancel check cannot see what pass 2 will insert or
 consume, nor an original that fails to cancel, and the same original
 listed twice is judged per occurrence — so confirm against open orders
 rather than relying on the code alone.



## OpenAPI

````yaml /proto-openapi/api/openapi.yaml post /api/v1/orders/batch-replace
openapi: 3.0.3
info:
  title: Monaco Protocol API
  description: REST API for the Monaco Protocol hybrid CLOB exchange.
  version: 1.0.0
servers:
  - url: https://staging.apimonaco.xyz
    description: Staging server (Testnet)
security: []
tags:
  - name: AccountsService
  - name: ApplicationsService
  - name: AuthService
  - name: BuildercodeRewardsService
  - name: CopyTradingService
  - name: DelegatedAgentsService
  - name: FaucetService
  - name: FeesService
  - name: HealthService
  - name: ManagedMarketsService
    description: |-
      Wallet-authenticated maker assignments. The signed session must match both
       configured maker user and application. Owner IDs are process fences, never auth.
       Only wallet sessions are supported; delegated-agent sessions receive 403.
  - name: MarginAccountsService
    description: |-
      Current public isolated-margin semantics:
       - a user has one parent margin account per application scope
       - opening orders create or reuse isolated position buckets under that parent
       - parent account creation is handled internally by margin workflows
  - name: MarketService
  - name: OrderbookService
  - name: OrdersService
  - name: PositionsService
    description: |-
      Current public isolated-margin semantics:
       - positions link to a parent margin account and, when applicable, a bucket id
       - opening orders create or reuse isolated position buckets under the parent
       - users can open another isolated position by reusing the parent account with a different market bucket
  - name: PulseService
  - name: SweeperService
  - name: TraderCodeService
  - name: TradesService
  - name: WhitelistService
  - name: WithdrawalsService
paths:
  /api/v1/orders/batch-replace:
    post:
      tags:
        - OrdersService
        - Orders
      summary: Batch replace orders
      description: |-
        Batch replace orders.

         Replace multiple orders in one engine step with per-item results: every
         original is cancelled first, then each replacement is placed in request
         order. A
         two-sided quote can therefore shift across its own resting prices in one
         call, and a replacement may use funds freed by any original in the batch.

         Failure semantics: an item that fails validation, or whose original
         cannot be found, leaves the original resting. An item whose replacement
         fails to PLACE (for example insufficient balance or self-trade
         prevention) reports the error with its original already cancelled.

         POST_ONLY_WOULD_CROSS is the exception: a post-only replacement that
         would cross is refused BEFORE the cancel pass, against the book as it
         will stand once the batch's own cancels are applied, so the item
         normally reports the error with its original still resting. It is not a
         guarantee — the pre-cancel check cannot see what pass 2 will insert or
         consume, nor an original that fails to cancel, and the same original
         listed twice is judged per occurrence — so confirm against open orders
         rather than relying on the code alone.
      operationId: batch_replace_orders
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchReplaceOrdersRequest'
        required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchReplaceOrdersResponse'
        '400':
          description: Invalid request
        '401':
          description: Authentication required
        '429':
          description: >-
            Order rate limit exceeded — each batch item counts against the
            per-account budget (and the account family's shared budget) and the
            whole request is rejected; retry after the interval in
            details.retryAfter
        '500':
          description: Internal server error
      security:
        - monacoSignature: []
        - monacoHttpSignature: []
components:
  schemas:
    BatchReplaceOrdersRequest:
      required:
        - orders
      type: object
      properties:
        orders:
          maxItems: 100
          minItems: 1
          type: array
          items:
            $ref: '#/components/schemas/BatchReplaceOrderItem'
      additionalProperties: false
    BatchReplaceOrdersResponse:
      type: object
      properties:
        totalRequested:
          example: 3
          type: integer
          description: Number of orders requested to replace
          format: int32
          nullable: true
        totalSucceeded:
          example: 3
          type: integer
          description: Number of orders successfully replaced
          format: int32
          nullable: true
        totalFailed:
          example: 0
          type: integer
          description: Number of replacements that failed
          format: int32
          nullable: true
        results:
          type: array
          items:
            $ref: '#/components/schemas/BatchReplaceResult'
          nullable: true
    BatchReplaceOrderItem:
      required:
        - orderId
      type: object
      properties:
        orderId:
          example: 123e4567-e89b-12d3-a456-426614174000
          type: string
          description: Order UUID to replace
          format: uuid
        price:
          example: '35500.00'
          type: string
          description: New limit price (if changing)
          nullable: true
        quantity:
          example: '0.7'
          type: string
          description: >-
            New TOTAL quantity (if changing). On a partially filled order the
            replacement rests total minus filled, and collateral is locked for
            that remainder only (FIX cancel/replace convention: LeavesQty =
            OrderQty - CumQty). Must exceed the filled amount. Omitted, the
            replacement keeps the unfilled remainder. Margin reduce-only orders
            follow the same rule: the quantity is the order's total, and what
            the replacement rests (total minus filled) must not exceed the live
            position it reduces.
          nullable: true
        useMasterBalance:
          example: false
          type: boolean
          description: Use master account balance for sub-account orders
          nullable: true
        postOnly:
          example: false
          type: boolean
          description: >-
            Post-only: reject instead of matching if this limit order would
            cross the book — rejected with HTTP 400 / gRPC INVALID_ARGUMENT
            carrying the structured error code POST_ONLY_WOULD_CROSS (REST
            error-envelope 'code' field; gRPC google.rpc.ErrorInfo reason; batch
            per-item error.code). Matching the 'post-only order would cross'
            message substring is a legacy fallback. LIMIT orders with GTC only;
            rejected on MARKET orders and IOC/FOK.
          nullable: true
        clientOrderId:
          example: quote-btc-1130-a
          type: string
          description: >-
            Client-assigned correlation handle, echoed back on order reads
            (detail and list) and on order WebSocket events. At most 64
            characters from [A-Za-z0-9._:-]; surrounding whitespace is trimmed
            before storage, and a blank or whitespace-only value is treated as
            absent. Uniqueness is enforced only among your orders that are
            RESTING on the book: an item reusing a value another of your resting
            orders still holds fails that item alone — the batch itself returns
            2xx / OK and the offending item's result slot carries error.code
            CLIENT_ORDER_ID_CONFLICT; no transport-level 409 / ALREADY_EXISTS is
            raised. An order that never rests — MARKET, IOC/FOK, or a LIMIT that
            fills completely on arrival — does not take the handle, and the
            value is released the moment any order reaches a terminal state. It
            is therefore NOT an idempotency key, though on this replace path a
            retry cannot double-execute: the request names the original order
            id, and the sequencer revalidates that original in memory and on the
            book at sequence time, so once the first replacement succeeds the
            original is gone and a retry is rejected with ORDER_NOT_FOUND rather
            than placing a second order. That code is itself ambiguous — the
            original may instead have filled or been cancelled — so the risk
            here is acting on a stale view, not duplicate execution. Reconcile a
            lost response against the order WebSocket stream, which carries this
            value on the submit acknowledgement and on fills, including for
            orders that never rest; order history is replica-backed and can omit
            an order that did land. The stream is not replayable and has no
            sequence number to backfill from, and its fan-out is non-persistent
            Core NATS: the service can re-establish an ended upstream
            subscription without closing your socket, so events can be missed
            while your connection still looks healthy. A matching event is
            therefore positive proof the order was accepted, but silence is
            NEVER evidence it was not, and no client-observable condition makes
            it so. Absent positive evidence the outcome is unresolved: hold and
            escalate rather than resubmitting. A replace item carries no order
            type or time-in-force and its original must still be RESTING, so the
            IOC/FOK and MARKET post-acceptance rejection shapes are unreachable
            here. Failures split by WHEN they occur, and the difference decides
            whether your original survives. Before sequencing: every validation
            failure — a malformed value included — fails ITS ITEM alone with a
            structured error.code (INVALID_CLIENT_ORDER_ID for a malformed
            handle, the same code batch-create uses) and no mutation and no
            event, batch-create parity; the whole request 400s only for an empty
            or oversize batch. (Earlier releases rejected the whole batch for a
            malformed value here.) A pre-cancel gate then drops two more classes
            before anything is cancelled — a handle conflict, and a post-only
            replacement that would cross the book as it will stand once this
            batch's originals are cancelled — so in the ordinary
            POST_ONLY_WOULD_CROSS case the item fails with its original still
            RESTING and untouched. After that the endpoint is CANCEL-FIRST: the
            original is cancelled in pass 1, so a residual placement failure
            then — a self-trade rejection, or a crossing that only became
            apparent in pass 2 — leaves the original CANCELLED and emits its
            cancellation events (terminal reason 'replaced') while the item
            reports the placement error and no replacement is placed. Never
            assume a failed item left your original resting; read results[] and
            the stream. Single ReplaceOrder differs: it is atomic, and a
            rejected replacement leaves the original untouched. Where no surface
            is conclusive, do not resubmit. A replacement is a new order with a
            new id, so it carries its own value and inherits nothing from the
            original — restate it to keep the handle.
          nullable: true
        selfTradePreventionMode:
          example: CANCEL_TAKER
          enum:
            - CANCEL_MAKER
            - CANCEL_TAKER
            - CANCEL_BOTH
            - SKIP
          type: string
          description: >-
            Per-order self-trade-prevention override for the replacement:
            CANCEL_MAKER, CANCEL_TAKER, CANCEL_BOTH, or SKIP (see the
            create-order field for the full semantics). A replacement is a new
            order with a new id, so it carries its own value and inherits
            nothing from the original — restate it to keep the override.
            Omitted, your wallet's configured default applies, else the platform
            default CANCEL_MAKER. An unknown value fails only this item, with
            error.code INVALID_SELF_TRADE_PREVENTION_MODE. The requested value
            is echoed back as selfTradePreventionMode on order reads, absent
            when omitted here.
          nullable: true
      additionalProperties: false
    BatchReplaceResult:
      type: object
      properties:
        originalOrderId:
          example: 123e4567-e89b-12d3-a456-426614174000
          type: string
          description: Original order UUID that was replaced
          format: uuid
          nullable: true
        newOrderId:
          example: 987e6543-e21b-12d3-a456-426614174000
          type: string
          description: New replacement order UUID (if successful)
          format: uuid
          nullable: true
        updatedFields:
          $ref: '#/components/schemas/UpdatedFields'
        matchResult:
          $ref: '#/components/schemas/MatchResult'
        error:
          $ref: '#/components/schemas/BatchReplaceError'
    UpdatedFields:
      type: object
      properties:
        price:
          example: '35500.00'
          type: string
          description: >-
            The replacement's limit price: the requested price, or the original
            order's price when price was omitted.
          nullable: true
        quantity:
          example: '0.7'
          type: string
          description: >-
            The replacement's total quantity: the requested quantity, or the
            original order's total when quantity was omitted. It is not the
            resting size: the replacement rests this total minus the
            already-filled amount, so a 100-lot with 60 filled reports 100 here
            and rests 40. Read the order's remainingQuantity for the resting
            size. Margin reduce-only replacements report their total the same
            way.
          nullable: true
    MatchResult:
      type: object
      properties:
        tradesCount:
          example: 2
          type: integer
          description: Number of trades generated by this order
          format: int32
          nullable: true
        totalFilled:
          example: '0.2'
          type: string
          description: Total quantity filled
          nullable: true
        remainingQuantity:
          example: '0.3'
          type: string
          description: Remaining unfilled quantity
          nullable: true
        averageFillPrice:
          example: '35100.00'
          type: string
          description: Volume-weighted average fill price
          nullable: true
        status:
          example: PARTIALLY_FILLED
          type: string
          description: Resulting order status after matching
          nullable: true
        actualSlippageBps:
          example: 15
          type: integer
          description: Actual slippage incurred in basis points
          format: int32
          nullable: true
        maxSlippageBps:
          example: 50
          type: integer
          description: Maximum slippage tolerance that was set
          format: int32
          nullable: true
        executionPriceRange:
          $ref: '#/components/schemas/ExecutionPriceRange'
    BatchReplaceError:
      type: object
      properties:
        code:
          example: ORDER_NOT_FOUND
          type: string
          description: Machine-readable error code
          nullable: true
        message:
          example: Order not found or already filled
          type: string
          description: Human-readable error message
          nullable: true
    ExecutionPriceRange:
      type: object
      properties:
        bestPrice:
          example: '2045.00'
          type: string
          description: Best execution price achieved
          nullable: true
        worstPrice:
          example: '2052.00'
          type: string
          description: Worst execution price in the fill
          nullable: true
  securitySchemes:
    monacoSignature:
      type: apiKey
      description: >-
        Ed25519 session-key request signing. Every authenticated request carries
        three headers: `X-Monaco-PublicKey` (64-char lowercase-hex session
        public key), `X-Monaco-Timestamp` (Unix milliseconds, within 30s of
        server time), and `X-Monaco-Signature` (hex ed25519 signature). The
        signature is over `METHOD\npath?query\ntimestamp_ms\nSHA256_hex(body)`,
        where the body hash is the SHA-256 of the empty byte string when there
        is no body. Obtain the session keypair from `POST
        /api/v1/auth/challenge` followed by `POST /api/v1/auth/verify`.
      name: X-Monaco-Signature
      in: header
    monacoHttpSignature:
      type: apiKey
      description: >-
        RFC 9421 Ed25519 session-key request signatures. Send Signature-Input,
        Signature, and Content-Digest together; never combine them with
        X-Monaco-* credentials. The monaco signature covers @method, @path,
        @query, and content-digest in that order, with created (Unix seconds
        within 30s of server time), keyid (registered lowercase-hex session
        public key), and alg=ed25519 parameters. Content-Digest uses RFC 9530
        sha-256 over the exact body bytes, including the empty body. Query
        coverage retains ordering and percent encoding. Timestamp freshness does
        not reject repeated identical requests; use endpoint idempotency where
        supported. Existing legacy signing remains supported during server-first
        migration; SDK RFC 9421 signing is opt-in. See
        https://docs.0xmonaco.com/reference/http-message-signatures for the
        complete profile and trust model.
      name: Signature
      in: header

````

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