NOONOO TRADINGStart in the bot

API Clock Errors: How a Few Seconds of Drift Can Reject Every Order

Your key permissions are correct and the balance is sufficient, but API orders keep getting rejected. The error includes timestamp or recvWindow. The cause may be neither an exchange outage nor the key: your computer clock differs from the exchange clock by a few seconds.

The Exchange Asks When Each Request Was Created

API orders carry signatures. A signature alone seems sufficient, but it can be copied and sent again. If someone intercepts your request and replays it an hour later, the same order could be submitted again. Exchanges therefore require a creation time and accept the request only when it is close to the current time.

Request Acceptance Conditions

The time written in your request: timestamp
The exchange's acceptance window: recvWindow

─────────────
To pass:
Server time − timestamp
must be at least 0 and no greater than recvWindow.

A request that is too old → Rejected to prevent replay attacks.
A request from the future relative to the server → Rejected as an impossible time.

The second condition is crucial. A slow clock reduces remaining window capacity, but a fast clock describes a request created at a time that has not yet arrived. It is rejected regardless of window width. Just a few seconds can therefore block 100% of orders.

What a Three-Second Difference Does

Assume an exchange defaults to recvWindow = 5,000ms, or five seconds.

Your Clock Is Three Seconds Fast
Exchange server: 12:00:00.000
Your PC: 12:00:03.000
recvWindow: 5,000ms

Submitted timestamp: 12:00:03.000
Server receipt: 12:00:00.080
Transmission delay: 80ms

Difference = 0.080 − 3.000 = −2.92 seconds

─────────────
Negative means in the server's future.
Condition fails → Every order is rejected.

Retrying produces the same result,
because the clock remains three seconds ahead.

A slow clock produces the more confusing symptom of sometimes working and sometimes failing.

Your Clock Is 4.6 Seconds Slow
recvWindow: 5,000ms
Clock lag: 4,600ms

Remaining allowance = 5,000 − 4,600 = 400ms

At 300ms network round-trip time:
100ms remains → Passes.
When the network briefly jumps to 500ms:
Budget exceeded → Rejected.

─────────────
The same code works ordinarily
but fails during volatile conditions.
The order fails precisely when most needed.

Latency rises when trading activity surges. A narrow allowance therefore causes failures specifically during sharp moves. Quiet-period logs look normal, making the cause harder to identify afterward.

Four Ways Clocks Drift

You might expect Windows to keep time automatically, but synchronization is less frequent than it may seem.

How Error Accumulates

Synchronization interval
Long default intervals let the hardware clock drift between updates.

Resume from sleep or hibernation
The computer may resume a few seconds out of sync.

Virtual machines and cloud hosts
Pausing and resuming the host can make the clock jump.

Failure to reach the time server
Firewalls or network problems can fail silently.
Error accumulates without a visible warning.

─────────────
In every case, the on-screen clock looks normal.
A few seconds of difference are not visually obvious.

The fourth case is especially troublesome. Failed synchronization does not necessarily show a warning. Drift grows over days until it crosses the window and orders suddenly stop. Since no code changed that day, investigation often looks in the wrong place.

Network Delay Uses the Same Budget

recvWindow is not reserved solely for clock error. The time taken to reach the server consumes the same allowance.

Items Sharing the Window
recvWindow: 5,000ms

− Clock error: 2,000ms
− Request creation and signing: 10ms
− One-way network travel: 150ms
− Server queue: 100ms

─────────────
Remaining allowance: 2,740ms

If clock error becomes 4,800ms:
Remaining allowance: −60ms → Rejected.

With the same clock drift, overseas servers or mobile tethering
cross the limit sooner.

Moving working code from a domestic server to an overseas host, or switching from wired to wireless networking, can therefore suddenly trigger rejections. Queues associated with rate-limit errors, HTTP 429, consume the allowance even faster.

Diagnose It by Querying Server Time

Measure the offset instead of guessing. Most exchanges provide an unauthenticated server-time endpoint.

Measuring the Offset

1) Record local time as t1.
2) Query server time and obtain s.
3) Record local time as t2.

Round-trip time = t2 − t1
Estimated local time at the response midpoint = (t1 + t2) ÷ 2

Offset = s − (t1 + t2) ÷ 2

─────────────
Example
t1 = 12:00:00.000
s = 12:00:02.100
t2 = 12:00:00.200

Round trip: 200ms; midpoint: 12:00:00.100
Offset = +2,000ms
→ Your clock is two seconds slow.

If the difference is within a few hundred milliseconds, investigate other causes: API-key permissions, IP allowlists, or other order-rejection reasons. If the discrepancy measures whole seconds, the clock is the likely cause.

Fix the OS Clock First, Then Add Offset Correction

There are two layers. Addressing only one allows recurrence.

① Synchronize the OS Clock: Required
Enable automatic time synchronization.
Run “Sync now” and verify success.
Use a shorter interval, measured in hours.

② Correct the Offset in Code: Recommended
Measure server time once at startup.
timestamp = Local time + Offset.
Remeasure every few tens of minutes.
Remeasure immediately after a clock-error response.

─────────────
With only ②, ledger and log times remain wrong.
With only ①, resume events and synchronization failures can cause recurrence.

A common mistake is omitting periodic remeasurement. An offset measured at startup becomes stale when a program runs for days. Even with correction, synchronize the OS clock: inaccurate fill and log timestamps make later position reconciliation or P&L verification ambiguous.

Simply Increasing recvWindow Does Not Resolve the Cause

The easiest response is widening the window. Rejections may disappear, but only the symptom has gone.

Widening the Window to 60 Seconds
recvWindow: 60,000ms
Clock error: 3,000ms → Passes.

But suppose the network stalls for 20 seconds and recovers.
An order created 20 seconds ago can execute now.

If price moved meanwhile,
the execution is no longer at the price you intended.

─────────────
The window is a replay-protection boundary.
Widening it allows delayed orders to come back to life.

A market entry delivered 20 seconds late has an uncertain fill price. Its cost resembles slippage. The window is a safeguard for discarding stale requests, not a tool for hiding clock drift, so avoid increasing it far beyond the default.

A More Dangerous Case: The Order Arrived, but Its Response Did Not

Immediate retry logic after an error can, depending on the circumstances, submit the same order twice.

How Duplicate Orders Happen

1) Send the order request.
2) The server accepts and executes it.
3) The response times out on the return trip.
4) Your local record says failure.
5) Automatic retry → The same order is accepted again.

Result:
Intended quantity: 0.1; actual quantity: 0.2.
Double quantity means double loss exposure.

─────────────
Prevention
Assign each order a unique ID.
Before retrying, query that ID.
If it already exists, do not resubmit.

Exchanges commonly accept client-specified order IDs and reject duplicates using the same ID. Include one when implementing retries. A local failure and a successful order whose response was lost may be indistinguishable locally; querying before retrying resolves that uncertainty. Partial fills complicate quantity reconciliation further.

Bot Checks

For automated trading, implement the following checks as standard behavior.

What to Include

Measure and log server-time offset at startup.
Remeasure periodically, for example every 30 minutes.
Alert when offset exceeds a threshold, such as one second.
After a clock error, remeasure and retry once.
Use unique order IDs and query before retrying.

─────────────
The most important point:
Record the clock error numerically.
Without it, the reason an order failed
may remain unknown permanently.

An error code alone is insufficient for reconstructing the cause later. Once the clock is corrected, this kind of fault leaves no visible trace unless the offset was logged.

Key Points

Exchanges accept requests whose timestamps are close to now.
A fast clock can reject every request regardless of window width.
A slow clock reduces allowance and can cause failures only during volatility.
Clock error, transmission delay, and queues share the recvWindow budget.
Automatic synchronization can fail silently.
Query server time to measure the offset numerically.
Use both OS synchronization and code-level correction.
Remeasure periodically; startup-only measurement is insufficient.
A much wider window lets stale orders execute later.
Retries require unique order IDs and querying before resubmission.

Time is part of API authentication, not optional metadata. If the code looks correct but orders fail, measuring the clock before inspecting more code may be faster.

Notice

The recvWindow values, latencies, offsets, and quantities are hypothetical examples, not measurements from a particular exchange. Default and maximum windows, server-time endpoints, and support and validity periods for client order IDs vary by exchange. Check your exchange's documentation and test with small amounts. Leveraged trading can lose all principal. Investment decisions and their consequences are your responsibility.

NOONOO TRADING invites you to follow live trading in our free chat.

Start in the bot

📈 OKX trading fee discount for new registrations

Register for the OKX Fee Discount →