Timestamp tolerance compared across exchange APIs
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.
Every venue that signs requests also checks that the request is fresh, and every one of them does it differently. The format differs (integer milliseconds, ISO 8601, epoch seconds), the width of the window differs, some venues treat a request from the future more harshly than a late one, and each returns its own error code. Get any of it wrong and the failure reads as an authentication problem.
Clock sync and timestamp errors covers how to diagnose drift. This page is the per-venue reference: the rule each venue documents, the code it returns, and the venue-specific detail that catches people who already know how the others work.
The matrix
| Venue | Timestamp field and format | Window | Request ahead of server time | Error |
|---|---|---|---|---|
| Binance Spot | timestamp parameter, milliseconds or microseconds | recvWindow: optional, default 5000 ms, maximum 60000 ms | Rejected at 1 second or more ahead | -1021 |
| Binance USDⓈ-M | As Spot | recvWindow default 5000 ms; we did not find a stated maximum | Same 1-second rule | -1021 |
| Bybit V5 | X-BAPI-TIMESTAMP header, milliseconds | X-BAPI-RECV-WINDOW: optional, default 5000 ms | Must be less than 1000 ms ahead | 10002 |
| OKX REST | OK-ACCESS-TIMESTAMP, ISO 8601 UTC with milliseconds | Rejected if more than 30 seconds from server time | Same 30-second tolerance | 50102; a malformed value is 50112 |
| OKX WebSocket login | Unix epoch seconds | Login request expires 30 seconds after its timestamp | — | Not documented in our fact card |
| Hyperliquid | nonce, recommended to be the current time in milliseconds | Must beat the smallest of the signer’s recent nonces, be unused, and fall inside a validity window around block time | Covered by the validity window | We did not find a nonce-specific error string |
Alpaca and IBKR do not appear because neither signs requests: Alpaca sends credentials as headers, and IBKR’s TWS API is a socket to a logged-in application. There is no timestamp to get wrong.
Where the venues actually differ
Binance: early is worse than late
Binance documents its check as pseudocode:
if (timestamp < (serverTime + 1 second) && (serverTime - timestamp) <= recvWindow)
A request can be up to recvWindow milliseconds late, but a request 1 second
or more ahead of server time fails regardless of recvWindow. That is why
-1021 INVALID_TIMESTAMP has two messages: “Timestamp for this request is
outside of the recvWindow.” and “Timestamp for this request was 1000ms ahead of
the server’s time.” A fast clock fails even at the maximum window, so widening
recvWindow does nothing for it. Binance recommends a window of 5000 ms or
less.
On spot, recvWindow accepts up to three decimal places, for microsecond
precision. On USDⓈ-M futures the same inequality applies and the default is
the same, but we did not find a maximum on the futures General Info page.
Do not carry the spot 60000 ms ceiling over to futures code. See
Binance API error -1021.
Bybit: the same shape, and the window is signed
Bybit’s guide states the rule as an inequality:
server_time - recv_window <= timestamp < server_time + 1000
Structurally that is Binance’s rule: late by up to the window, less than a
second early. The difference is that Bybit puts recv_window inside the
signature pre-hash, alongside the timestamp and API key. The window value is
authenticated, and the value you sign must be the value you send.
The guide says a smaller window “is more secure”, recommends keeping local time
NTP-synchronised, and exposes server time at GET /v5/market/time. A request
outside the window returns 10002, “The request time exceeds the time window
range.” The same error table also lists -1, “request expired: o@0, now[]
diff[]”; we did not find further explanation of it. See
Bybit API error 10002.
OKX: a wider window with a stricter format
Thirty seconds is far more forgiving than a 5000 ms default, which moves the
usual failure from drift to format. OKX wants ISO 8601 UTC with milliseconds,
for example 2020-12-08T09:08:57.715Z, and its docs name local timezone
offset as the most common cause of 50102.
OKX separates the two failures: a timestamp that is well-formed but too far
from server time returns 50102, “Timestamp request expired.”; a malformed one
returns 50112, “Invalid OK-ACCESS-TIMESTAMP.” The docs recommend syncing via
GET /api/v5/public/time before placing orders.
WebSocket login uses epoch seconds, not ISO 8601. A timestamp helper shared between REST and WebSocket code will be wrong for one of them. See OKX API error 50102.
Hyperliquid: a nonce is a replay guard, not a freshness check
Hyperliquid has no receive window. Every /exchange request carries a nonce,
and the docs recommend using the current millisecond timestamp. The rules:
- The venue stores a set of the highest recent nonces per signer. A new nonce must be larger than the smallest in that set and never used before.
- The nonce must fall within a validity window relative to the block’s timestamp. The set size and the window are on the nonces and API wallets page.
- Nonces are tracked per signer. With an API wallet, the signer is the agent address, so sub-accounts signed by the same API wallet share one nonce set. The docs’ advice is a separate API wallet per sub-account or process.
Freshness in the CEX sense is the optional expiresAfter field, a millisecond
timestamp that some actions accept. User-signed actions such as USDC transfers
do not support it, and actions cancelled for a stale expiresAfter are charged
more heavily against the address-based rate limit.
The docs also warn that once an API wallet is deregistered and its nonce state pruned, previously signed actions can be replayed. Generate new wallets rather than reusing addresses. See Hyperliquid API setup.
“Action already expired” is a different thing: Hyperliquid’s support FAQ
documents it for the web app, and we did not find it mapped to the API’s
expiresAfter.
What to do in code
Run NTP and measure the delta. At startup, fetch the venue’s server time, compare it with local time and log the difference. Bybit and OKX document their server-time endpoints above; the clock-sync page covers Binance.
Generate the timestamp once per request. OKX requires the pre-hash timestamp to equal the header value, and Bybit signs the timestamp too. A second call to the clock between signing and sending is a mismatch.
Format per venue, not per project. Integer milliseconds for Binance and Bybit, ISO 8601 with milliseconds for OKX REST, epoch seconds for OKX WebSocket login. Put the formatter inside each venue’s signer.
Do not widen the window to fix drift. On Binance and Bybit it cannot help a fast clock, and on every venue it trades away replay protection to hide a broken clock.
On Hyperliquid, one API wallet per process with an atomic nonce counter that can be fast-forwarded to the current millisecond, as the docs suggest for porting CEX bots.
Treat timestamp errors as non-retryable. -1021, 10002 and 50102 will
recur until the clock is fixed; a retry loop only adds rate-limit pressure. See
authentication errors across exchanges.
FAQ
What is the maximum recvWindow on Binance?
On Binance Spot, recvWindow defaults to 5000 ms and has a maximum of 60000
ms, and Binance recommends 5000 ms or less. For USDⓈ-M futures the default is
also 5000 ms, but we did not find a maximum stated on the futures General Info
page, so do not assume the spot ceiling applies.
Why are my requests rejected when my clock is ahead?
Binance and Bybit both reject a request whose timestamp is a second or more ahead of server time, independently of the receive window. A fast clock therefore fails even with the largest allowed window. Synchronise the clock with NTP rather than adjusting the window.
How much clock skew does OKX allow?
OKX rejects REST requests whose timestamp differs from server time by more than
30 seconds, returning 50102. The format must be ISO 8601 UTC with
milliseconds; a malformed value returns 50112 instead. WebSocket login uses
Unix epoch seconds and expires 30 seconds after its timestamp.
How does Hyperliquid check request timestamps?
Hyperliquid uses a nonce, recommended to be the current millisecond timestamp. It must be higher than the smallest of the signer’s stored recent nonces, never reused, and inside a validity window around block time. Nonces are tracked per signer, so processes sharing one API wallet share one nonce set.