Skip to main content
The Polymarket matching engine undergoes restarts for maintenance and upgrades. This page covers how to detect and handle downtime, the post-restart post-only period, and where to get advance notice of changes.

Announcements

Matching engine changes — planned restarts, updates, and maintenance windows — are announced before they happen in these channels:

Telegram

Join the Polymarket Trading APIs channel for real-time announcements.

Discord

Join the #trading-apis channel in the Polymarket Discord.
Announcements typically include what’s changing, the scheduled time, and the expected downtime window. The goal is ~2 days notice when possible.

Handling HTTP 425

During a restart window, the CLOB API returns HTTP 425 (Too Early) on all order-related endpoints. This tells your client that the matching engine is restarting and will be back shortly. After every restart, the matching engine enters post-only mode for 2 minutes. During this period, cancels are accepted and new orders must use postOnly: true; non-post-only orders are rejected.
1

Detect 425

When you receive an HTTP 425 response, the matching engine is restarting. Do not treat this as a permanent error.
2

Back off and retry

Wait and retry with exponential backoff. Start at 1–2 seconds and increase the interval on each retry.
3

Handle post-only mode

Once 425 responses stop, the engine is back online but remains in post-only mode for 2 minutes. During that period, only cancels and orders with postOnly: true are accepted.

Code Examples

Check the HTTP status code on responses to the CLOB API and retry on 425:
const CLOB_HOST = "https://api.copilot.markets/clob";

async function postWithRetry(path: string, body: any, headers: Record<string, string>) {
  const MAX_RETRIES = 10;
  let delay = 1000;

  for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
    const response = await fetch(`${CLOB_HOST}${path}`, {
      method: "POST",
      headers: { "Content-Type": "application/json", ...headers },
      body: JSON.stringify(body),
    });

    if (response.status === 425) {
      console.log(`Engine restarting, retrying in ${delay / 1000}s...`);
      await new Promise((r) => setTimeout(r, delay));
      delay = Math.min(delay * 2, 30000);
      continue;
    }

    return response;
  }
  throw new Error("Engine restart exceeded maximum retry attempts");
}

Restricted Trading Modes

During restricted trading modes, order placement behavior changes for POST /order and POST /orders. Cancel endpoints continue to accept cancels unless trading is fully disabled.

Cancel-Only Mode

In cancel-only mode, new orders are rejected, but cancel requests are still accepted. POST /order and POST /orders return 503:
{
  "error": "Trading is currently cancel-only. New orders are not accepted, but cancels are allowed."
}

Post-Only Mode

After every restart, the matching engine enters post-only mode for 2 minutes. Cancel requests are accepted and new orders must use postOnly: true. Non-post-only orders are rejected. POST /order returns 503 with a retry delay in both the response body and the Retry-After HTTP header:
{
  "error": "post-only mode: only post-only orders and cancels are allowed",
  "code": "post_only_mode",
  "retry_after_seconds": 79
}
POST /orders returns per-order errors for non-post-only orders in the batch:
[
  {
    "errorMsg": "post-only mode: only post-only orders and cancels are allowed",
    "orderID": "",
    "takingAmount": "",
    "makingAmount": "",
    "status": "",
    "success": true
  },
  {
    "errorMsg": "post-only mode: only post-only orders and cancels are allowed",
    "orderID": "",
    "takingAmount": "",
    "makingAmount": "",
    "status": "",
    "success": true
  }
]
When you receive either restricted-mode response, do not retry the same non-post-only order unchanged. Cancel existing orders, retry after the indicated delay when one is provided, or resubmit eligible maker orders with postOnly: true.

Best Practices

  • Subscribe to announcement channels — get notified before restarts happen so you can prepare
  • Handle 425 gracefully — treat it as a temporary condition, not an error; your retry logic should resume automatically
  • Handle 503 mode responses on order placement — cancel-only and post-only responses require changing order flow, not blind retrying
  • Avoid aggressive retries — the engine needs time to reload orderbooks; rapid-fire retries won’t speed things up and may hit rate limits once the engine is back
  • Log restart events — track when your client encounters 425s to correlate with announced maintenance windows