Skip to main content
This is the integration recipe. For the full contract — every field, every error code, the email behaviour — see Maintenance notifications.

What you are trying to do

Know that a window is coming early enough to do whatever your side does about it — pull quotes, flatten, hand over to another venue, page someone — then sit it out and resume when the platform is back. What you do with the warning is yours. This page is about getting the signal right and at the right time. Two endpoints give you everything you need, and they answer different questions. Use both — neither replaces the other. Both take your partner API key in X-Api-Key.
Plan from the schedule. Act on the status. The two can disagree for a few minutes, and the section on when they disagree explains why that is normal rather than a bug.

The recipe

1. Poll the schedule, slowly

Once a minute is plenty — the response is cached for 5 seconds and the data rarely changes.
?scope=trading returns both trading windows and full-platform (all) windows, because a full freeze stops trading too. A withdrawals window does not affect order flow; leave the filter in place and you will not see one. Keep the windows you get, keyed by id. Pass the response’s generatedAt back as your next from so you never miss a transition. If the schedule answers 404 not_found, or /status has no maintenance object, the feature is not on in that environment. Treat that as “no information”, not as “all clear”, and keep your own error handling.

2. Decide your lead time and trigger your own wind-down

Pick how much warning you need — ten minutes is a common ask. Then:
run your wind-down is whatever that means for you. Some desks stop placing and cancel everything, some only widen, some move flow elsewhere, some just notify a human. We do not assume which. Announced windows normally arrive 24 hours or more ahead, so this fires with plenty of warning. An incident window can arrive with no notice at all — handle that case too (see step 5).

3. Know what still works while it runs

A window is an announcement, not a switch: nothing in the order path reads it. What you see while one runs depends on the work behind it:
  • While the works are under way (a release, a database failover), order placement answers 503 trading_temporarily_unavailable or 503 shard_owner_unavailable. Do not treat that as a rejected order and do not retry it hard. Cancels go through the same exchange and can fail the same way (shard_owner_unavailable, exchange_unavailable, exchange_transport_error, or 202 cancel_pending), so the safe time to unwind is before the window starts. See Errors you may see during maintenance.
  • If the platform-wide freeze is also on (frozen: true on /status), placement and cancel-all answer 503 platform_frozen. Single cancel and cancel-batch stay open under the freeze by design, so you can still unwind.
  • Declaring a window does not cancel your resting orders or touch your positions.

4. Resume on status, never on the clock

This is the part that most often gets written wrong.
Do not resume at expectedEndAt. That field is a promise we make to you, not a timer:
  • We can finish early. A window closes when we mark it complete, and that can be well before the time we announced.
  • We sometimes run late. The window stays in_progress past expectedEndAt, and you will get an extended notice if we move the promise. Resuming on the old clock would put you back into a surface that is still down.
maintenance.trading.status == "operational" is the only signal that means “we are back”.

5. Handle the no-notice case

Not every outage is announced in advance. Your /status poll is what catches those: degraded is the same alert that pages our own on-call, so you learn when we do. There is no window id under it and no promised end, because nobody declared it.

When the two disagree

A window shows startsAt: 19:00, it is 19:05, and /status still says operational. Nothing is broken. A window becomes real when an operator presses Start, not when the clock reaches startsAt. The announced time is when we intend to begin; the status is what has actually happened. Start can be pressed before or after startsAt, so either can come first. What that means for you:
  • Use startsAt to prepare — stop quoting, pull orders. Being flat a few minutes early costs you little.
  • Never infer the end from the start. A window that has not started cannot end.
  • A scheduled window that has not started by its expectedEndAt disappears from the feed. Until then it stays listed as scheduled, even after startsAt. Once it is gone it is not going to happen as announced: drop it and resume when /status says operational. If we later reschedule, start or cancel it, it reappears under the same id.
If a window regularly starts far from its announced time and that is costing you, tell your account manager — we would rather tighten our side than have you widen your lead time.

Worth knowing

One partner, one bucket per endpoint. All of your API keys share one limit on each endpoint — 600 requests per minute at the default rate tier — plus 600 per minute per IP (/status shares its IP bucket with /notices). The cadence on this page, the schedule once a minute and /status every 30 seconds, uses 1 and 2 of those 600 respectively. See Rate limits. Upsert by id. You will be shown windows you already have for up to a minute after they change — that overlap is deliberate, so a transition that was mid-commit when you polled still reaches you. Subscribe a mailbox too. The API is the machine signal; the email is how a human on your side finds out. Ask your account manager to add an address — you get a notice when a window is scheduled, rescheduled, started, extended, completed or cancelled. See Email notifications. If you cannot reach us at all, treat it as an outage you have not been told about: stop quoting and back off. A 401 means your key is missing or was not accepted (malformed, unknown, revoked, expired, or called from outside its IP allowlist), and a 403 partner_key_required means it is a self-service key — neither means the platform is down. These endpoints require a partner key.