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

# Maker Protection

> How Maker Protection delays liquidity-taking orders on selected Derivatives markets, and what it changes for REST, WebSocket, and FIX clients

Maker Protection is a short, fixed delay applied to liquidity-taking order actions on selected Derivatives markets. It gives resting maker orders time to react to new information before an incoming aggressor can trade against them.

## Overview

On a market with Maker Protection, any order action that could take liquidity — that is, any order not marked post-only — is held for the market's configured window before it reaches the matching engine. Post-only placements and all cancellations are never held.

|                |                                                                                          |
| :------------- | :--------------------------------------------------------------------------------------- |
| **Window**     | 20 ms at launch, published per market as `makerProtectionMillis`. Never more than 100 ms |
| **Applies to** | Selected Derivatives (Futures) markets. Spot is unaffected                               |
| **Live from**  | 15 September 2026                                                                        |
| **Exempt**     | Post-only orders, all cancellations, block trades and other off-book flow                |
| **Protocols**  | Identical behaviour on REST, WebSocket, and FIX                                          |
| **Clients**    | Applied per market to every client equally — there are no per-account exemptions         |

The delay sits in the order gateway in front of the matching engine, not in the engine itself. Every client path passes through it, so the behaviour is the same whichever protocol you use. Because the hold happens before the request is sequenced into the engine, a held order takes its queue position at release, not at receipt.

<Note>
  The only way to avoid the delay is to submit the order as post-only. A limit order without post-only is held regardless of whether it would in fact have rested — the classification is by order type, not by outcome.
</Note>

## Which markets have it

Read `makerProtectionMillis` from the instruments endpoints. It is the authoritative, live source — the market list changes as the rollout progresses.

```bash theme={null}
curl "https://futures.kraken.com/derivatives/api/v3/instruments"
```

```json theme={null}
{
  "symbol": "PF_ATOMUSD",
  "type": "flexible_futures",
  "tradeable": true,
  "makerProtectionMillis": 20
}
```

The field is present on both `GET /instruments` and `GET /trading/instruments`, and is **omitted entirely** when the market has no Maker Protection configured. Treat "absent" and "zero" as the same thing: no delay.

The ten most liquid linear perpetual markets are excluded at every phase, so that active taker flow in the majors is not slowed. Every perpetual listed after 15 September 2026 has Maker Protection applied from launch. Additions to the list are announced on [status.kraken.com](https://status.kraken.com) ahead of each maintenance window.

<AccordionGroup>
  <Accordion title="Phase 1 markets — 15 September 2026">
    These 57 markets are covered at launch. This list is a point-in-time record; query `makerProtectionMillis` for the current set.

    `PF_2ZUSD` · `PF_ALCHUSD` · `PF_ANTHROPICXUSD` · `PF_ASTERUSD` · `PF_ASTRUSD` · `PF_ATOMUSD` · `PF_BELUSD` · `PF_BRENTOILUSD` · `PF_CHFUSD` · `PF_CKBUSD` · `PF_CTSIUSD` · `PF_CYBERUSD` · `PF_DEEPUSD` · `PF_DEGENUSD` · `PF_DYMUSD` · `PF_ENJUSD` · `PF_GALAUSD` · `PF_GRIFFAINUSD` · `PF_HMSTRUSD` · `PF_ICPUSD` · `PF_IDUSD` · `PF_IOSTUSD` · `PF_LCAPUSD` · `PF_LDOUSD` · `PF_LRCUSD` · `PF_METISUSD` · `PF_MINAUSD` · `PF_MTLUSD` · `PF_NATGASUSD` · `PF_NBISUSD` · `PF_NEIROUSD` · `PF_OPENAIXUSD` · `PF_OPUSD` · `PF_PENGUUSD` · `PF_PROMPTUSD` · `PF_SAMSUNGUSD` · `PF_SKHYUSD` · `PF_SNDKUSD` · `PF_SOONUSD` · `PF_SOXLUSD` · `PF_SOXSUSD` · `PF_TUSD` · `PF_US100USD` · `PF_VELOUSD` · `PF_VIRTUALUSD` · `PF_WIFUSD` · `PF_WTIOILUSD` · `PF_XAGUSD` · `PF_XAUUSD` · `PF_XCNUSD` · `PF_XCUUSD` · `PF_YFIUSD` · `PF_ZILUSD` · `PI_ETHUSD` · `PI_LTCUSD` · `PI_XBTUSD` · `PI_XRPUSD`
  </Accordion>
</AccordionGroup>

## What is and isn't delayed

| Action                                            | Held?  | Notes                                                       |
| :------------------------------------------------ | :----- | :---------------------------------------------------------- |
| Limit, IOC, FOK or market order                   | Yes    | Any order not marked post-only                              |
| Post-only order                                   | **No** | Never held, on any market                                   |
| Edit of an order that can rest and take liquidity | Yes    | Classified by the target order's type                       |
| Edit of a resting post-only order                 | **No** | An edit cannot change an order's type                       |
| Edit naming an order your account has not placed  | **No** | Forwarded immediately; the engine rejects unknown orders    |
| Stop / take-profit / trailing-stop placement      | **No** | Placing the trigger is not a liquidity-taking action        |
| The order a trigger fires                         | Yes    | Held inside the engine, unless the fired order is post-only |
| Order group placing a new non-post-only parent    | Yes    | Classified by the new parent order                          |
| Order group attaching to an existing order        | **No** | Places only triggers                                        |
| Cancel, cancel-all, cancel-all-after              | **No** | Cancellations are never delayed                             |

<Note>
  An edit is classified against the order **your account placed**, not against what your order-status feed has caught up on. An edit sent immediately after a placement is therefore held on the same terms as one sent to a long-resting order, even though the target may not be visible to you yet. Only an edit naming an identifier your account has not placed — and that no resting non-post-only order answers to — is exempt.
</Note>

## Order lifecycle

```mermaid theme={null}
sequenceDiagram
    participant C as Client
    participant GW as Order gateway
    participant ME as Matching engine
    C->>GW: Place order not marked post-only
    GW->>GW: Hold for makerProtectionMillis
    Note over C,GW: No new order state is exposed
    GW->>ME: Release unchanged after the window
    ME-->>C: Open, filled or rejected
```

Four properties are worth designing around:

* **Your order is validated at release, not at submission.** The request is held untouched and only reaches the matching engine when the window expires, so margin, position limits, price collars and market status are all evaluated at that later moment. See [What can happen while an order is held](#what-can-happen-while-an-order-is-held).
* **The full window is always served.** The hold is decided from market conditions at submission. If the liquidity that made your order aggressive disappears during the window, the order still waits out the delay before entering the book. Held orders are not re-evaluated.
* **The queue is FIFO.** With a fixed delay, holds are released in the order they were accepted. A later order cannot overtake an earlier one inside the queue.
* **The contract is "at least N ms".** Orders you submit are released by a timer and land very close to the configured window. Orders fired by a **trigger** are different: they wait in the matching engine and are released by the next event it processes, so on a quiet market a stop or take-profit can be held noticeably longer than the configured window. Never assume the delay is exact, and never infer it by measuring latency — read `makerProtectionMillis`, which can be changed at any time.

## What can happen while an order is held

A held order is not yet in the book, and it is not guaranteed to get there. The window is an interval in which your order can be rejected by events that have nothing to do with your own trading:

| Event during the window                                   | Outcome for the held order                                                                                                                                   |
| :-------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| You cancel it, or your own cancel-all covers it           | The cancel is acknowledged, and the order still reaches matching — converted so that it cannot rest. See [Cancelling a held order](#cancelling-a-held-order) |
| Your `cancelallordersafter` dead man's switch fires       | Purged, so it cannot land after your resting orders were pulled                                                                                              |
| The market is suspended                                   | Rejected with `marketSuspended`                                                                                                                              |
| Your account is de-risked or liquidated                   | Swept, so it cannot book straight after your account was flattened                                                                                           |
| Margin, position limits or price collars move against you | Evaluated at release, so an order that was valid on submission can still reject                                                                              |
| One of your own resting orders is in the way at release   | That maker is cancelled, whatever self-trade strategy your account has set. See [Self-trade prevention](#self-trade-prevention)                              |

The practical consequence: an order that returns a rejection roughly one window after you sent it has usually not been rejected on its own merits. Read the returned status rather than assuming the placement itself was malformed.

## Self-trade prevention

A liquidity-taking order released from a hold **always cancels the resting order of your own it would match**, overriding the self-trade strategy configured on your account (`GET` / `PUT /self-trade-strategy`). It applies across the whole account tree — the maker may belong to your account, your master, a sibling or a sub-account.

This closes an evasion the hold would otherwise leave open: post-only orders are never held, so an account could drop one in front of its own held taker and have the default `REJECT_TAKER` strategy kill the release, recalling committed aggression for the price of one extra message.

| Situation                                   | Resolution                                                                                                                                                                                 |
| :------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Released taker meets your own resting order | `CANCEL_MAKER` is forced. The maker is cancelled with reason `CANCELLED_BY_SELF_TRADE` and your taker trades                                                                               |
| The released order is FOK, or an RFQ        | Your configured strategy applies as normal. An all-or-nothing order is admitted against depth that includes that maker, so cancelling it would part-fill an order that asked for all of it |
| The order was never held                    | Your configured strategy applies as normal                                                                                                                                                 |

<Warning>
  On the edit path this changes **which of your two orders dies**. A self-matching edit already destroyed the order being amended rather than refusing the edit; with the hold, the maker is cancelled and the amended order trades. If you rely on `REJECT_TAKER` to protect resting quotes on a Maker Protection market, that protection does not hold against your own released aggressors.
</Warning>

## Behaviour by protocol

There is no `held` order state anywhere in the public API. Maker Protection surfaces as extra latency on aggressive placements, not as a new state to model.

<Tabs>
  <Tab title="REST">
    The connection is simply held for the duration of the delay, and the response carries the final outcome — `placed`, `filled`, `cancelled` or a rejection — exactly as it would without Maker Protection.

    Set your client-side request timeout comfortably above the market's `makerProtectionMillis`. A timeout tighter than the window will abandon requests that are about to succeed. The window can never exceed 100 ms, so a single timeout budget covers every market.

    <Warning>
      If you send `processBefore` on an aggressive order, its deadline must allow for the hold. The deadline is evaluated **after** the delay, so a `processBefore` shorter than `makerProtectionMillis` rejects every time with `wouldProcessAfterSpecifiedTime`.
    </Warning>
  </Tab>

  <Tab title="WebSocket">
    Nothing is published while an order is held. You receive the normal `open_orders` and `fills` events once the order is released and the engine acts on it — the only observable difference is that they arrive about `makerProtectionMillis` later.
  </Tab>

  <Tab title="FIX">
    The FIX gateway sends an advisory `ExecutionReport (8)` when a request is held. It is advisory only: it does not advance the order's lifecycle, and the real `New` or `Replaced` acknowledgement still follows at release. Do not treat it as a terminal state.

    **A held placement** reports Pending New:

    | Tag                   | Value                                  |
    | :-------------------- | :------------------------------------- |
    | `39` (`OrdStatus`)    | `A` — Pending New                      |
    | `150` (`ExecType`)    | `A` — Pending New                      |
    | `11` (`ClOrdID`)      | Your order's client order ID           |
    | `37` (`OrderID`)      | **Not present**                        |
    | `41` (`OrigClOrdID`)  | Not present                            |
    | `58` (`Text`)         | `held by aggressor speedbump for 20ms` |
    | `60` (`TransactTime`) | When the hold began                    |

    The engine does not assign an order UID until the request is released, so no `OrderID` exists yet — `ClOrdID` is your only handle on the order during the window.

    **A held amend** reports Pending Replace instead:

    | Tag                  | Value                                                         |
    | :------------------- | :------------------------------------------------------------ |
    | `39` (`OrdStatus`)   | `E` — Pending Replace                                         |
    | `150` (`ExecType`)   | `E` — Pending Replace                                         |
    | `11` (`ClOrdID`)     | The amend's client order ID                                   |
    | `41` (`OrigClOrdID`) | The client order ID of the order being amended                |
    | `37` (`OrderID`)     | **Present** — the target order already has an engine order ID |
    | `58` (`Text`)        | `held by aggressor speedbump for 20ms`                        |

    On both reports, `AvgPx (6)` and `GrossTradeAmt (381)` are sent as `0`. FIX requires them, but they carry no meaning before the order reaches the book. The `Text` value interpolates the market's configured window, so it reads `350ms` on a market configured for 350 ms.

    <Note>
      Two cases produce **no** advisory at all: an order that was already acknowledged before the notice arrived (the signal would be stale), and a held edit that was submitted over REST or the web platform rather than FIX (there is no FIX amend `ClOrdID` to report against).
    </Note>

    **Cancelling a held amend** appears as the Pending Replace advisory, then the cancel's own `ExecutionReport`, then the amend's outcome at release — fills, or a reject.

    <Note>
      Where the engine refuses an edit by cancelling the order instead — a quantity that resolves to nothing, an edit that would match your own resting order, an edit whose own fill drives available margin negative, or a converted amend whose remainder may not rest — the trading channel carries a **rejection** with the fault, not an amend acknowledgement. Read the reject rather than assuming the order was amended.
    </Note>
  </Tab>
</Tabs>

## Cancelling a held order

You can cancel an order while it is held. Cancels are never delayed, so a cancel sent immediately after a placement can overtake it inside the window.

**A cancel cannot recall committed aggression.** Cancelling inside the window does not withdraw the order: it removes the order's right to *rest*, not its obligation to *trade*. The held request is rewritten to immediate-or-cancel and released at its original expiry, where it takes whatever liquidity it can and the remainder is discarded instead of joining the book.

<Warning>
  This is the easiest thing to get wrong. `cancel` on an aggressive held order means "do not leave anything resting", not "forget I sent this". If the market has moved in your favour during the window, a cancelled hold **still fills**. Release time never moves, so a cancel cannot be used to buy a free look at the market.
</Warning>

Address the cancel by order ID or by client order ID. For a **held placement** the client order ID is your only option — the engine has not assigned an order ID yet. A **held amend** is different: the order it targets is already resting, so it has an order ID you can use.

What a cancel does inside the window depends on the shape of the request being held:

| Held request                                                   | A cancel inside the window                                                                                                                                                                                             |
| :------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Limit placement                                                | **Converted.** The cancel is acknowledged, and the order is released as immediate-or-cancel at its original expiry                                                                                                     |
| Amend of a resting limit order                                 | **Converted in place.** See [Cancelling while an edit is held](#cancelling-while-an-edit-is-held)                                                                                                                      |
| IOC, FOK or market order                                       | **Not claimable** — there is nothing to convert, since the order could never have rested. The cancel goes to the engine, finds no order there yet, and returns `ORDER_NOT_FOUND`. **The order still lands at release** |
| Post-only placement (only held behind an aggressor in a batch) | **Withdrawn.** It could not have taken liquidity, so cancelling it is you pulling your own quote. Reported as cancelled                                                                                                |
| Order group                                                    | **Not claimable.** See [Order groups cannot be cancelled while held](#order-groups-cannot-be-cancelled-while-held)                                                                                                     |
| Trigger-fired limit order (held inside the engine)             | **Converted**, exactly as a limit placement                                                                                                                                                                            |
| Trigger-fired IOC, FOK or market order                         | **Not claimable**, exactly as the placement case                                                                                                                                                                       |

After release, timing is ordinary:

| Timing                                                          | Result                                                             |
| :-------------------------------------------------------------- | :----------------------------------------------------------------- |
| Cancel lands after release, order resting                       | An ordinary cancel of a live order                                 |
| Cancel lands after release, order was IOC/FOK, or was converted | `ORDER_NOT_FOUND` — the order already filled or expired at release |

<Note>
  **Edits cannot claim a held order.** Only a cancel can — a single cancel, or your own cancel-all. When both a held placement and a held amend of the same order exist, **amends are claimed first, and every matching amend is claimed**, not just the first.
</Note>

### How a converted placement is reported

A conversion is not a new state and not a new status code. The cancel and the order are answered separately:

|                                          | Reported as                                                                                       |
| :--------------------------------------- | :------------------------------------------------------------------------------------------------ |
| The cancel                               | Success — order status `cancelled`. It is answered by the gateway, not the engine                 |
| The order, if it trades at release       | Fills, exactly as an immediate-or-cancel would report them. A partial fill discards the remainder |
| The order, if it cannot trade at release | REST v3 `iocWouldNotExecute`; `IOC_WOULD_ENTER_BOOK` on market data                               |

So a cancelled hold produces **two responses**: the cancel's, and the order's own — the latter about one window later. An `iocWouldNotExecute` on an order you submitted as a plain limit order is the signature of this path.

### How a withdrawn hold is reported

The claims that do withdraw an order — a cancel of a held post-only order, and an admin cancel-all — never reach the matching engine, so they are reported locally:

| Interface         | Reported as                                      |
| :---------------- | :----------------------------------------------- |
| REST v3           | Order status `cancelled`                         |
| Market data / SBE | Order error `WOULD_PROCESS_AFTER_SPECIFIED_TIME` |

There is no dedicated "cancelled while held" value in the public enums. Distinguish this case by the cancel you sent, not by the code.

### Cancelling while an edit is held

Amending a resting order so that it would cross the book is claimable too, and the outcome is the one instruction that reads least like a cancel.

While the amend is held, **the original order is still live in the book, unchanged, at its old price** — the amendment has not reached the matching engine, so the order can still trade on its old terms during the window.

A cancel of that order inside the window is **absorbed**: it is answered by the gateway and never forwarded, so the engine does not cancel the target. At release, the amendment is rewritten to reprice that same order to the price you committed to *and* to give up its right to rest. Same order ID, same client order ID, same order group.

Both of your instructions therefore take effect — the amend crosses, and what it would have left behind does not sit on the book:

```mermaid theme={null}
sequenceDiagram
    participant C as Client
    participant GW as Order gateway
    participant ME as Matching engine
    C->>GW: Amend resting order so it would cross
    GW->>GW: Hold the amendment
    Note over ME: Original order still resting at its old price
    C->>GW: Cancel the order
    GW-->>C: Cancelled (answered here, not forwarded)
    GW->>ME: Amendment released, rewritten so it cannot rest
    ME-->>C: Fills, or the order is gone
```

A converted amend has exactly two outcomes. Either it trades and leaves nothing resting, or the order is gone:

| At release                                                                                                                                             | Outcome                                                                                                                                                                                                    |
| :----------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The reprice crosses                                                                                                                                    | It trades. Any residual is discarded rather than rested                                                                                                                                                    |
| The engine refuses the edit — margin, a post-only market, open interest, a price collar, a suspended market, or an order type that cannot be converted | **The order is cancelled** rather than left resting, and the edit response carries the refusal reason. A suspension is included: the order is removed even though the market is no longer accepting orders |
| The target is genuinely gone                                                                                                                           | The edit is rejected with `orderForEditNotFound`, and the cancel you were already given is the honest answer                                                                                               |

<Note>
  `orderForEditNotFound` is **not** the expected outcome of cancelling during a held amend. If you see it, the order had genuinely already left the book — it is not the signature of this race.
</Note>

On the v4 API, a converted amend that part-fills and is then refused because the remainder may not rest reports `REJECTED_AFTER_EXECUTION`, so the fills that are already booked are visible rather than hidden behind an error.

Two amends of the same order can be held at once. A cancel claims **both**, because converting only one would let the other release as a plain edit and re-rest the order the cancel has just been acknowledged for.

### Order groups cannot be cancelled while held

An order group whose new parent order would take liquidity is held, but it is **not** a claimable hold. A cancel addressed to the parent order ID during the window finds nothing, returns `ORDER_NOT_FOUND`, and **the group still goes live when the window expires**. You cannot stop the group inside the window; cancel it after it is live.

<Warning>
  **Known limitation — OCO siblings do not see held legs.** A group member whose activated order is held inside the engine is invisible to sibling cancellation and reduction, which walk booked orders and registered triggers only. If an opposing sibling fills during the hold window, the held leg is not removed, and **both legs of the group can go live**. Reconcile group state from fills after any sibling fill on a Maker Protection market rather than assuming one leg cancelled the other. A fix is in progress.
</Warning>

### Reusing a client order ID inside the window

If you cancel an order and immediately replace it reusing the same client order ID, both can be in flight within one window. While that is true:

* The replacement is addressable **by order ID only**. A cancel by client order ID still resolves to the first order, not the replacement.
* If the first order is somehow still live when the replacement is released, the engine rejects the replacement with `clientOrderIdAlreadyExist`.

Either wait out the window before reusing an identifier, or address in-flight cancels by order ID.

<Tip>
  If you need "get me out entirely, with nothing left resting and nothing new trading", there is no request that does it inside the window. Wait out the window — it is capped at 100 ms — and then cancel. Anything you send during the hold can only change whether the order rests.
</Tip>

## Cancel-all while orders are held

Your own `cancelallorders` claims every held placement and held amend in scope, on exactly the same terms as a single cancel: placements are converted to immediate-or-cancel, and amends are converted in place.

Because a held amend's target is already resting at the engine, a sweep that claims one also **carves that order out of the sweep**: it is deliberately left in the book, and the converted amend removes it when it releases. So a `cancelallorders` on a Maker Protection market can return having left an order resting, by design.

| Request                                    | Effect on held orders                                                      | Carve-out                                            |
| :----------------------------------------- | :------------------------------------------------------------------------- | :--------------------------------------------------- |
| Your own `cancelallorders`                 | Converted, as above                                                        | Yes — the targets of claimed amends are left resting |
| `cancelallordersafter` (dead man's switch) | **Purged.** A held order cannot land after your resting orders were pulled | No                                                   |
| An exchange or admin cancel-all            | **Purged.** Nothing lands after the book is wiped                          | No                                                   |

Two consequences worth designing around:

* **A carved-out bracket parent keeps its group's triggers.** They are not cancelled with the rest of the sweep, so the position the amend fills is not left without its take-profit and stop-loss.
* **An order spared by one sweep stays spared.** Once an amend has been converted, the order it targets is left alone by later cancel-alls too, until that amend releases and removes it.

Claimed holds are reported through their own placement or edit responses and are **not** listed in the cancel-all response.

## Batch orders

A batch is not held as a single unit. The window starts at the **first liquidity-taking instruction** in the batch:

* Instructions **before** the first aggressor are forwarded immediately.
* The first aggressor and everything **after** it wait out the window together.
* **Cancels are forwarded immediately wherever they appear.** A cancel placed **after** the order it targets claims that order's hold within the same batch — converting it, exactly as a separate cancel would. A cancel placed **before** it cannot claim anything: at that point the placement does not exist yet, so the cancel resolves against whatever order you already had under that identifier.

The order you write your instructions in therefore decides which of them wait. If you want a passive instruction to reach the book without delay, put it ahead of any aggressive instruction in the batch.

Self-trade resolution is decided per member, from that member's own delay rather than from its position in the batch. A post-only member, or one on a market without Maker Protection, that waits behind an aggressor in the same batch keeps the self-trade strategy your account configured.

## Reference

| Value                                | Where                                          | Meaning                                                                                                                            |
| :----------------------------------- | :--------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
| `makerProtectionMillis`              | `GET /instruments`, `GET /trading/instruments` | The market's hold in milliseconds. Absent when not configured                                                                      |
| `wouldProcessAfterSpecifiedTime`     | REST order status                              | `processBefore` deadline expired — including a deadline shorter than the hold                                                      |
| `WOULD_PROCESS_AFTER_SPECIFIED_TIME` | Market data order error                        | Also reported for a hold withdrawn before release: a cancelled post-only hold, or an admin cancel-all                              |
| `iocWouldNotExecute`                 | REST order status                              | A converted hold could not trade at release. Seen on orders you submitted as plain limit orders                                    |
| `IOC_WOULD_ENTER_BOOK`               | Market data order error                        | The same case on market data                                                                                                       |
| `REJECTED_AFTER_EXECUTION`           | v4 edit response                               | A converted amend part-filled and was then refused because the remainder may not rest                                              |
| `CANCELLED_BY_SELF_TRADE`            | Order update reason                            | Your resting order was cancelled so a released aggressor of yours could trade                                                      |
| `ORDER_NOT_FOUND`                    | Cancel response                                | The cancel arrived after release and the order had terminated, or it named a hold that is not claimable                            |
| `orderForEditNotFound`               | REST order status                              | A held edit was released after its target order had genuinely left the book. **Not** the outcome of cancelling during a held amend |
| `marketSuspended`                    | REST order status                              | The market was suspended while the order was held                                                                                  |
| `clientOrderIdAlreadyExist`          | REST order status                              | A replacement reused a client order ID whose original was still live at release                                                    |

## Testing

Maker Protection has been enabled on the Phase 1 markets in the client UAT environment since 27 August 2026. Test your order handling there before the production date. Contact your account manager for UAT access.

Worth exercising specifically, since each one has a non-obvious outcome:

* **Cancel during a hold.** Confirm you handle the order still filling after a successful cancel, and that you do not retry the placement.
* **Cancel during a held amend.** Confirm you handle a successful cancel followed by the amend's own fills or reject, rather than expecting `orderForEditNotFound`.
* **Your own resting order in the way.** Confirm you tolerate a maker of yours being cancelled with `CANCELLED_BY_SELF_TRADE` even with `REJECT_TAKER` set.
* **Batch instruction ordering**, and **client-side timeouts** above the market's `makerProtectionMillis`.

The UAT environment and production run the same build at launch, so behaviour verified there is the behaviour you get on 15 September.
