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

# Rate Limits

> Order, movement, settings, copy trading, read, authentication, public application read, and WebSocket limits: budgets, headers, and how to back off.

Monaco meters order entry at admission, before the matching engine:

* Budgets are keyed to your **account**, not your IP or session; delegated agent sessions share the owning account's budget.
* Costs are counted in **order items**: a batch of N costs N, and is never partially admitted.
* Two classes (**order creation**, **risk reduction**), each with a per-second and a per-minute window; a request must fit both.
* Every account also shares a **family budget** (4× the account caps) with its master and sibling sub-accounts. The movement, settings-write and read budgets are tiered the same way.
* Every other write that reaches the matching engine draws a budget of its own before it gets there: fund **movements**, **settings writes**, and the copy trading **stops** and **closes** (see [Settings and copy trading writes](#settings-and-copy-trading-writes)).
* The public **authentication** endpoints run before any account is known, and the public **application reporting** endpoints have no account at all, so both are metered per client address instead (see [Authentication](#authentication) and [Public application reads](#public-application-reads)).

## Current defaults

Order budgets are in items; the rest in requests. Every budget is per account except authentication and public application reads (per client address) and the WebSocket limits (per connection, or per account on each server instance). Values may be tuned per environment; the [headers](#budget-headers) are authoritative for the order budgets.

<table>
  <thead>
    <tr>
      <th rowSpan={2}>Class</th>
      <th colSpan={2}>Public</th>
      <th colSpan={2}>PrivateLink</th>
    </tr>

    <tr>
      <th>Per second</th>
      <th>Per minute</th>
      <th>Per second</th>
      <th>Per minute</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Order creation</td>
      <td>500</td>
      <td>15,000</td>
      <td>2,000</td>
      <td>60,000</td>
    </tr>

    <tr>
      <td>Risk reduction</td>
      <td>1,000</td>
      <td>30,000</td>
      <td>4,000</td>
      <td>120,000</td>
    </tr>
  </tbody>
</table>

| Budget | Limit |
| - | - |
| Account family (shared) | 4× the account caps: any order class or ingress, movements, settings writes, and reads |
| Movements (withdrawals, collateral transfers, copy position margin adds, TraderCodes reward transfers, BuilderCodes payout claims) | 20 ops/s (burst 60) |
| Settings writes (lead trader profile, follow create/edit, self-trade-prevention default) | 1 write/s (burst 10) |
| Follow stops | 1 stop/s (burst 20) |
| Copy position closes | 1 close/s (burst 5) |
| Reads (authenticated) | 30 requests/s (burst 100) |
| Authentication (`/auth/challenge` and `/auth/verify`) | 60 requests/min (burst 120), per client address |
| Public application reads (`/applications/{orders,users,movements,balances,stats}`) | 60 requests/min (burst 120), per client address |
| WebSocket inbound messages | 20 messages/s (burst 1,200), per connection |
| Resting orders (book state, not a rate) | 500 per market, 4,000 per account (per engine shard), see [Resting-order caps](#resting-order-caps) |

The PrivateLink budgets apply to gRPC order entry from your own AWS VPC over [PrivateLink](/developers/privatelink). PrivateLink carries gRPC trading and WebSocket feeds but not REST. It is available on staging today, for a fixed monthly cost on request. Reach out to the Monaco team for details.

<Note>
  Budgets are enforced **per API task**, not fleet-wide, and both fleets autoscale (production: REST 1→10 tasks, gRPC 2→40), so an account spread across tasks can be admitted above the published figure. Movements, settings writes, follow stops, copy position closes, reads, and authentication return no headers; pace those by the `Retry-After` of a `429`.
</Note>

## The two classes

| Class | Covers | Budget |
| - | - | - |
| **Order creation** | `POST /api/v1/orders`, replaces, batch create/replace items, `POST /api/v1/orders/twap`, `POST /api/v1/positions/{id}/tp-sl` (`reduceOnly` items included) | 1× (base) |
| **Risk reduction** | Every cancel: `/orders/cancel`, `/orders/batch-cancel`, conditional and TWAP cancels, `/orders/batch-cancel-all` (and by-pair). Every position close: `POST /api/v1/positions/{id}/close`, `POST /api/v1/positions/batch-close-all` | 2× creation |

* `reduceOnly` never buys the larger budget: a reduce-only order you place draws order creation. Margin previews draw no order budget.
* **A position close costs one risk-reduction item**, so spending your creation budget never stops you getting out. `batch-close-all` draws one item per open position it closes (an empty call draws one). The first 100 are charged before anything is sent: over budget, the whole call is refused with `429` and nothing is closed. Past 100 open positions the rest are charged 100 at a time, and those the budget does not cover are not sent: they come back in `results` with `RATE_LIMIT_EXCEEDED`, so call again after the interval.
* **Mass cancel costs one item per call**: `batch-cancel-all` draws one item however many orders it cancels.
* **TP/SL attach costs one item per call**, whether it carries a take-profit, a stop-loss, or both.
* A batch over 100 items is rejected with `400` before any budget is drawn.

## Account families

* Every gated request must fit your account budget **and** the shared family budget (4×); a family-tier rejection says so in its message.
* An account with no sub-accounts can never hit its family budget; a large family is bounded to 4× total.
* Movements, settings writes and reads are tiered the same way: a per-account budget plus a family budget at the same multiplier, shared by the master and every sub-account.

## Budget headers

Order endpoints, position closes and TP/SL attach included, return your live budget (movement, settings, copy trading, read, and authentication endpoints return none):

| Header | Meaning |
| - | - |
| `X-RateLimit-Limit-Second` | Per-second cap for the class this request drew from |
| `X-RateLimit-Remaining-Second` | Items admittable now (the tighter of account and family) |
| `X-RateLimit-Limit-Minute` | Per-minute cap |
| `X-RateLimit-Remaining-Minute` | Items admittable now under the minute window (bounded by the spike allowance) |

* Keys are emitted lowercase; REST lookup is case-insensitive, gRPC metadata requires the lowercase form. On a `429` the headers report the class, window, and tier that denied.

## When you are over budget

* **REST**: `429`, code `RATE_LIMIT_EXCEEDED`, `Retry-After` + `details.retryAfter` (seconds): a second for a spike, up to a minute for sustained overflow.
* **gRPC**: `RESOURCE_EXHAUSTED` with a `google.rpc.RetryInfo` detail.
* Honor the interval: exponential back-off with jitter, never a tight resubmit loop. Movements, settings writes, follow stops and copy position closes draw their own budgets and return the same contract.
* **Enforcement is gated.** The order budgets (position closes included) and the movement budget (TraderCodes reward transfers and BuilderCodes payout claims included) are always measured, but reject only once `order_rate_limit_enforced` and `movement_rate_limit_enforced` respectively are turned on for the environment — both default off, and until then an over-budget request is admitted with a warn log. Stay inside the published budgets rather than waiting for a rejection to tell you.
* A `429` is decided before the request reaches the matching engine, so nothing was applied: a throttled order, close, transfer or claim is safe to resend once the interval has passed.

### Edge escalation

* An IP that keeps flooding after repeated `429`s is edge-blocked **five minutes**; again within ten minutes, **an hour**. The public REST and gRPC paths also share a per-IP volume guard, sized above what one account family can legitimately send under the published budgets above (not above whatever fan-out across API tasks may admit). Counters are per IP (and per Cloudflare data center) across every public environment host, so a flood against one environment blocks that address on the others too. PrivateLink traffic never passes the edge.
* An edge block is a `429` with `details.reason` (`edge_429_flood` / `edge_request_flood`) and `details.retryAfter`, but **no** `Retry-After` header; gRPC sees a non-OK transport status (typically `UNAVAILABLE` or `UNKNOWN`), so treat those as throttling too. Blocks don't shorten while you retry into them.

## Resting-order caps

Separately from the rate windows, the matching engine caps how many orders one account keeps **resting on the book**:

| Scope | Cap |
| - | - |
| Per market | 500 |
| Per account (per engine shard) | 4,000 |

* A rest-capable order (a LIMIT that is not IOC/FOK) past a cap is rejected with `400` / `INVALID_ARGUMENT`, code `ORDER_CAP_EXCEEDED`; the message names the binding scope (`market` or `account`).
* This is a book-state guard, not a rate limit: nothing to wait out. Fills and cancels free slots immediately.
* MARKET and IOC/FOK orders never rest, so they are always exempt; you can always take liquidity to get out.
* Replaces are exempt: a replace frees its own slot, so repricing at the cap always works.
* `batch-cancel-all` is exempt from these resting-order caps and is the fastest way to free many slots. It is not unlimited overall: it still matches at most **20,000** orders — see [Other limits](#other-limits).
* Conditional (TP/SL) and TWAP orders keep their own dedicated caps and do not count here until they trigger onto the book.

## Settings and copy trading writes

These writes each send one command to the matching engine and spend none of the order or movement budgets, so they have small per-account budgets of their own:

| Budget | Covers | Limit |
| - | - | - |
| **Settings writes** | `PUT /api/v1/copy-trading/leaders/me`, `POST /api/v1/copy-trading/follows` (create and edit), `PUT /api/v1/accounts/self-trade-prevention` | 1 write/s, burst 10, shared by all three |
| **Follow stops** | `POST /api/v1/copy-trading/follows/{followId}/stop` | 1 stop/s, burst 20 |
| **Copy position closes** | `POST /api/v1/copy-trading/follows/{followId}/close-positions`, `POST /api/v1/copy-trading/follows/close-positions` | 1 close/s, burst 5, shared by both |

* The settings burst covers following the most leaders one account may follow, one after another. Past it, pace writes at one per second.
* **The three budgets are separate.** Edits never spend the stop budget and closes never spend it either, so you can always stop every follow you hold in a row.
* Sub-accounts share a family settings-write budget (4×) with their master. Registering and following are master-account writes, and a master's writes count toward that family budget too.
* **Enforced from the first request.** Unlike the order, movement, read and authentication budgets, these have no warn-only phase: past the budget REST returns `429` with `Retry-After` (and `details.retryAfter`) and gRPC returns `RESOURCE_EXHAUSTED` with a `google.rpc.RetryInfo` detail. No budget headers are returned.
* A request refused before the budget is reached — a delegated agent session, or a sub-account registering as a lead trader or following — spends nothing.

## Reads

Every **authenticated read** costs one request from a per-account read budget:

* **Counts**: signed REST `GET`s, the `POST` previews under `/api/v1/margin/…/simulate-order-risk` and `POST /api/v1/copy-trading/follows/preview`, and every gRPC `Get*` / `List*` / `Simulate*` plus `CopyTradingService/PreviewFollow`. **Doesn't**: writes, public market data, the public application reporting endpoints (see [Public application reads](#public-application-reads)).
* Delegated sessions share the owner's budget; sub-accounts have their own read budget and share a family read budget (4×) with their master, so a family polling in parallel is bounded like one owner.
* Over budget: same `429` / `RESOURCE_EXHAUSTED` contract, no headers, interval typically one second.
* **Enforcement is gated.** Like the order, movement and authentication budgets, this one ships warn-only: until `read_rate_limit_enforced` is turned on for the environment — it defaults off — the limiter measures every read but admits an over-budget one with a warn log and returns no `429`. Stay inside the published budget rather than waiting for a rejection to tell you.

The three `simulate-order-risk` previews and the copy trading follow preview (`POST /api/v1/copy-trading/follows/preview`, gRPC `PreviewFollow`) also draw a second, **dedicated preview budget**, one budget for all four, keyed on your account family like the other budgets on this page: delegated sessions share the owner's budget, and sub-accounts share a family budget with their master. A preview runs inside the matching engine on a lane every user shares, so one client sweeping sizes can starve every other order form; the engine also gives each account family a share of that lane, and all four previews draw on the same share (a refusal there is a `503` / `UNAVAILABLE` to retry). This budget is measured today and ships warn-only: until `order_risk_preview_rate_limit_enforced` is turned on for the environment — it defaults off — an over-budget preview is admitted with a warn log. Once enforced, REST returns `429` with `Retry-After` (and `details.retryAfter`) and gRPC returns `RESOURCE_EXHAUSTED` with a `google.rpc.RetryInfo` detail; its values will be published here when enforcement turns on. Debounce order-form previews (the reference UI waits 500 ms and cancels an in-flight preview when the size changes) and never poll them.

Prefer the WebSocket streams for anything you would otherwise poll; events cost no read budget.

## WebSocket connections

Each server instance enforces these on its own connections; they are not shared across instances.

| Bound | Value |
| - | - |
| Inbound application frames (`Authenticate`, `Subscribe`, `Unsubscribe`, `Ping`, or anything unparseable; protocol `Ping` and message fragments count, `Pong`/`Close` do not) | 20/s sustained, burst 1,200, per connection |
| Inbound bytes, per connection | Enough for a full re-subscribe frame at open plus normal traffic; frames count by size, and a burst of maximum-size frames is refused |
| Subscriptions per connection | 1,024 |
| Connections per account, per server instance | 50 |

Values may be tuned per environment. The default burst covers the full subscription cap plus headroom for an `Authenticate` and a few `Ping`s, so adding a full subscription set one channel per `Subscribe` frame on an open connection stays within budget.

* A channel past the subscription cap gets an `Error` frame with code `SUBSCRIPTION_LIMIT` naming that channel; the connection and its other subscriptions stay open.
* An authentication past the connection cap gets an `Error` frame with code `CONNECTION_LIMIT`, and that connection closes. Close a connection you no longer need before opening another.
* A channel string may be at most 128 characters of printable ASCII, excluding `"` and `\`; others get `INVALID_SUBSCRIPTION`.
* The first frame past the frame or byte budget gets an `Error` frame with code `MESSAGE_RATE_LIMIT`; the connection then closes with `1008`. Batch channels into few `Subscribe` frames and slow down before reconnecting. See [Inbound message rate](/reference/websockets#inbound-message-rate-close-code-1008).

## Authentication

`POST /api/v1/auth/challenge` and `POST /api/v1/auth/verify` (gRPC `AuthService/Challenge` and `Verify`) run before any account exists, so they are metered per **client address** (the connecting IP as Cloudflare sees it), not per account:

* The two endpoints share one budget per address: **60 requests/min** sustained, burst **120**. A login (one challenge plus one verify) costs two; a scripted loop is held to one request per second.
* Over budget: the same contract as above (REST `429` with `Retry-After` and `details.retryAfter`; gRPC `RESOURCE_EXHAUSTED` with a `google.rpc.RetryInfo` detail), decided before the signature is examined; a throttled request is never reported as an authentication failure.
* **Enforcement is gated.** This budget ships warn-only: until `auth_rate_limit_enforced` is turned on for the environment — it defaults off — an over-budget request is admitted with a warn log and no `429` is returned. Stay inside the published budget rather than waiting for a rejection to tell you.
* Every other authenticated call is unaffected. Keep a session alive with `POST /api/v1/auth/refresh` instead of re-authenticating, and reuse one session across your processes.
* PrivateLink access carries no client address and is not metered here.

## Public application reads

`GET /api/v1/applications/{orders,users,movements,balances,stats}` (gRPC `ApplicationsService/ListAppOrders`, `ListAppUsers`, `ListAppMovements`, `ListAppBalances`, `GetAppStats`) are public and select their application by `clientId`, so they are metered per **client address** (the connecting IP as Cloudflare sees it):

* All five share one budget per address: **60 requests/min** sustained, burst **120**.
* Over budget: REST `429` with `Retry-After` and `details.retryAfter`; gRPC `RESOURCE_EXHAUSTED` with a `google.rpc.RetryInfo` detail.
* **Always enforced.** Unlike the budgets above, this one has no warn-only phase.
* Walk a listing with the largest `pageSize` you can use (up to 1000) rather than many small pages.
* PrivateLink access carries no client address and is not metered here.

## Other limits

* Batches take at most **100 items**; cancel-all matches at most **20,000** orders; both reject with `400` and change no order (an over-cap cancel-all still costs its one item). See [Batch Create](/developers/trade#batch-create).
* New deposit-address registrations share a **service-wide** admission limit; re-registering an existing address is never limited. See [Registered Deposit Addresses](/sdk/typescript/vault#registered-deposit-addresses).
* Trader code edits are bounded per rolling hour. See [Trader Codes](/developers/tradercodes).
* The testnet faucet enforces a daily quota per wallet and app. See [Faucet](/developers/faucet).


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