OKX Error 54094
Cool-off period now extends to REST/WebSocket, webhooks rejected server-side
You pointed a TradingView alert at OKX, and one day the webhook started coming back with nothing but a 54094. Your API key hasn't expired, the IP allowlist hasn't changed, and you're nowhere near the rate limit — but OKX cool-off period API rejection is, as of 2026-07-07, expected behaviour by design, not something you misconfigured. This post walks the OKX "Notice on Upgrade to the Futures Cool-off Period" and the OKX API v5 changelog against your webhook payload, field by field, so you know exactly which orders get rejected, which don't, and whether existing users need to worry.
This post isn't a verdict on whether OKX designed the mechanism well — cool-off is a retail-protection feature and we're not going to argue against it. It also isn't a "how to get around it" guide, because the rule is enforced server-side and no client-side trick can bypass it. Scope is narrow: what 54094 means, why your webhook hits it, and what you can change in your flow.
54094 — your reduce-only close orders are always allowed through; second, strategy orders and copy-trading orders are rejected regardless of whether they open or close — stricter than a plain REST order — so any bot placing orders through OKX's built-in strategy engine is fully blocked; third, if you configured a cool-off period before the 2026-07-07 upgrade, you keep the old behaviour, which only restricts web/app manual orders and leaves the API untouched, until you actively reset the cool-off period yourself.What It Looks Like: HTTP 200 but the Order Never Landed
The most confusing thing about this error is that its HTTP status code is 200 — not 4xx, not 5xx. Your HTTP client will tell you "request succeeded," but the JSON body OKX returned has an sCode (per-order status code) of 54094, with a message copied straight from the official changelog:
Order rejected. The cool-off period is active for the current instId.What it actually means: this was never an order. OKX received your request, verified the signature, ran risk checks, and then rejected it at the order-placement layer because the cool-off period is active — so the entire HTTP request lifecycle counts as "successful," but the trade you thought you placed never reached the matching engine. If your webhook consumer only looks at the HTTP status code and treats 200 as success, you get the classic "response is 200 but positions never moved" scenario. This kind of error doesn't make noise. It fails silently — and it will stay silent until you reconcile the account and find out yourself.
Why This Happens: The Rule Lives in the API Layer, Not Your Code
OKX posted the notice on 2026-07-03, brought it into effect on 2026-07-07, and started phased rollout in specific regions from 2026-07-16, extending what used to be a web/app-only cool-off period to "REST API, WebSocket, third-party authorization (including Broker OAuth, Agent Trade Kit, etc.), trading bots" (from the second paragraph of the notice). Which means: once you actively enable cool-off on your OKX account, open/increase orders arriving via any channel during that window are server-side rejected.
Where does the official notice stop? The notice states in plain text that "any orders to open or increase positions submitted through the above channels will be rejected. Orders to reduce or close positions are not affected." — open/increase rejected, reduce/close allowed. Strategy orders and copy trading get their own line: "Strategy orders and copy trading orders will be rejected regardless of whether they are for opening or closing positions." — rejected regardless of open or close. Everything else in this post is us mapping those two sentences to fields in your webhook payload; the specifics are inferred, not additional official wording.
The error code 54094 itself was added in the 2026-07-07 API changelog, and the changelog's Cool-off period order rejection section states "While a user's cool-off period is active, non reduce-only orders on SWAP and FUTURES instruments covered by the cool-off are rejected server-side." — which also pins down the instrument scope: SWAP (perpetuals) and FUTURES (dated futures). Spot and options are not listed in the original text.
Which Orders Get Rejected, Which Don't
This table cross-references both the notice and the changelog — the first column is the order channel, the next three are common scenarios. Use it to map your deployment path by path and see which routes get blocked by 54094.
| Order channel / type | Open / increase | Reduce-only close | Strategy orders (including TP/SL algo) |
|---|---|---|---|
| Web / app manual | Rejected (unchanged behaviour) | Allowed | Rejected |
| REST API (TradingView webhook → your server → OKX) | Rejected with 54094 | Allowed | Rejected |
| WebSocket order placement | Rejected with 54094 | Allowed | Rejected |
| Broker OAuth / Agent Trade Kit (third-party authorization) | Rejected with 54094 | Allowed | Rejected |
| OKX built-in Trading Bot | Rejected with 54094 | Allowed | Rejected |
| Copy Trading | Rejected (regardless of open/close) | Rejected (regardless of open/close) | Rejected (regardless of open/close) |
Scope affected by the OKX cool-off upgrade. Sources: OKX Help Center Notice on Upgrade to the Futures Cool-off Period (published 2026-07-03) plus the Cool-off period order rejection section in the OKX API v5 changelog dated 2026-07-07. Instruments: SWAP and FUTURES; spot and options are outside the original scope. Verified July 2026.
How the TVSBot / TradingView Webhook Payload Maps to This
The TVSBot webhook payload schema has a field called reduce_only, type bool, default false. Whether that field is boolean true is what tells OKX to treat this as a reduce-only close and let it through — the difference between true and false is huge:
| Payload shape | What happens during OKX cool-off | ||
|---|---|---|---|
| action=buy / sell, no reduce_only set | { "action": "buy", "symbol": "BTC-USDT-SWAP" } | Rejected with 54094 — because reduce_only defaults to false | |
| action=close (TVSBot rewrites this into reduce_only) | { "action": "close", "symbol": "BTC-USDT-SWAP" } | Allowed — TVSBot's order service always forces reduce_only=true for action=close | |
| action=buy / sell, payload explicitly sets reduce_only=true | { "action": "sell", "reduce_only": true } | Allowed — the payload declares it as a reduce-only close | |
| action=buy / sell, payload sets reduce_only=false | { "action": "buy", "reduce_only": false } | Rejected with 54094 — an explicit open/increase order |
What this means for a Pine Script strategy author: if your webhook fires from a strategy.entry()-triggered alert, it's an open/increase by nature and cool-off blocks it. Alerts from strategy.close() or strategy.exit() can pass through, but only if your payload template sets action to "close" (or explicitly writes reduce_only: true). The qty_type trap article has a full field-by-field payload reference — worth reading alongside this one.
reduce_only isn't there as a key, it's going out as false (the TVSBot-side default) — and during cool-off every such alert will be rejected by OKX. Nothing will warn you about this ahead of time; either you fix it now, or the next time you enter cool-off you'll find out from your account reconciliation.Three Ways to Fix It — Pick One
Once you're seeing 54094, you have three choices: cancel the cool-off, wait it out, or refactor your flow around reduce-only closes. There is no fourth option — this is server-side rejection at OKX and no client-side change matters.
| Fix | When it fits | Constraints |
|---|---|---|
| Cancel the cool-off | You didn't actually want it — set it by mistake or for a test | If you set it under the new version (post-2026-07-07), you can turn it off. If you set it under the old version, the notice explicitly says current cool-off period cannot be terminated early — you wait it out |
| Wait for it to expire | You set the cool-off deliberately, to protect yourself | During the window, all open/increase orders come back as 54094 unless you switch them to reduce-only |
| Switch to a "client-side position state machine" + reduce-only closes | The strategy runs long enough that hitting 54094 manually every time isn't sustainable | Development cost, and you can no longer lean on OKX-side strategy orders (TP/SL) for protection — you have to track price client-side and fire reduce-only market orders to close, similar to the pattern in the failover-design post |
Three fixes for 54094. In practice most TVSBot users take the third route — rewrite payloads to explicitly carry action=close or reduce_only=true so the close path stays open, and accept that opening has to wait or that cool-off has to come off. Verified July 2026.
Do Existing Users Get Grandfathered?
Yes, conditionally. The third paragraph of the official notice reads "Users who configured the cool-off period before this upgrade will remain on the existing service, which only restricts orders placed via the web and app. These users will not be subject to the expanded restrictions introduced in this upgrade." — anyone who had a cool-off configured before 2026-07-07 stays on the old behaviour (web/app only) until the current cool-off window ends.
There is a switching point coming up, though: if you want the new, full protection, the notice recommends "we recommend re-enabling the cool-off period after your current one expires" — reset the cool-off once the old one expires, and the new rules apply. So the moment you next re-enable your cool-off, "I had cool-off configured previously and my API just kept working" flips automatically to the new regime. If you want cool-off to keep leaving your API alone, don't re-enable it.
Diagnostic Order When You See 54094
This checklist is meant to be run top-to-bottom the moment you see 54094 — you don't need to memorise it, just stop at whichever step catches your case. The first three confirm it's really this mechanism; the last three tell you how to respond.
- Read the HTTP body, not just the status code. OKX returns HTTP 200 +
sCode: "54094"for this error, so any consumer that only checks the HTTP status will miss it entirely. Your webhook consumer must parse the JSON body and inspectsCode. - Confirm your OKX account actually has an active cool-off period. Go to Account > Trading > Cool-off Period in the OKX web console and see whether status is Active and how much time is left. If it's Inactive,
54094isn't coming from this — check sub-account settings or Broker OAuth scopes instead. - Confirm the instrument is SWAP or FUTURES. The changelog only names those two categories. If your
instIdisBTC-USDT(spot) or options, a54094is likely something else — go back to the OKX API sCode reference and look up the latest definition for that code. - Check whether this order is reduce-only. Look at
reduce_onlyin the payload — is it present, is ittrue? For TVSBot, settingactionto"close"counts too — the order service will translate it intoreduce_only=trueautomatically. - Check whether it's a strategy or copy-trading order. Orders going through OKX's built-in strategy engine, or a sub-account set up for copy trading, are rejected during cool-off regardless of open or close. Either switch to your own REST order placement, or wait for cool-off to end.
- Decide: kill the cool-off or refactor the flow. Old-version cool-offs can't be ended early — the notice is explicit — so wait. New-version cool-offs can be turned off. The long-term fix is to split your strategy logic into "opens might get blocked by cool-off, closes always go through reduce-only," so that the next time this happens the whole pipeline doesn't stall.
The Honest Section: We Can't Get Around This Either
Any automated trading system running on OKX — including our own TVSBot — has to obey this rule. It's enforced server-side by OKX, not client-side; no SaaS, broker, or bot service can bypass it for you. For example, TVSBot doesn't pre-check cool-off before placing an order (OKX doesn't expose a query API for it), and when a rejection comes back we keep the raw 54094 message on the order record so you can see in the dashboard exactly why it didn't go through — but that only solves "you find out faster," not "the order actually went out." Cool-off exists to make you cool off; any service claiming to "automatically bypass cool-off" is working against the design intent, we don't do that, and you shouldn't use a third-party service that does either.
Common Questions
I never turned on a cool-off period myself — why am I still getting 54094?
Does spot get blocked by 54094?
SWAP and FUTURES instruments covered by the cool-off are rejected server-side" — only SWAP (perpetuals) and FUTURES (dated futures). Spot and options fall outside that sentence. That's the state at the time this was verified; if OKX later extends cool-off to more instrument types it wouldn't be surprising — cool-off is a protection feature, and expanding it is the natural direction.Does TVSBot's dry-run mode hit 54094?
During cool-off, can I add OKX-side TP / SL algo orders?
Since existing users are grandfathered, should I set a cool-off now to lock myself into the old behaviour?
Will Binance / Bybit / Bitget follow?
Get started
Pipe TradingView signals into OKX for automated order placement — TVSBot is non-custodial, uses your own API key, exposes fine-grained reduce_only control in the payload, supports dry-run before you go live, and preserves every raw error message on the order record so when 54094 shows up you can see immediately whether it's cool-off or something else.
Get started for free- TradingView Webhook Not Working? A Complete Debugging Flowchart
- Why Your TradingView Auto Trading Position Size Is Wrong
- Which Exchanges Actually Support TradingView Webhook Signals?
- What Happens to Your Automated Strategy When TradingView or the Exchange Goes Down?
- A Non-Custodial Trading Bot API Key Permission Checklist