Bybit vs OKX API: auth, account modes and liquidation scope
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.
Bybit and OKX both run a “V5” API, both put most errors in the response body, and both set margin behaviour through account-level modes. That makes them look interchangeable. The difference that matters most is not in the signing code — it is what a single liquidation can reach, which each venue sets through a different account setting.
This page is for developers adding the second venue. It covers mechanism only, quotes no fees or quotas, and recommends neither. For the wider checklist, see choosing an exchange for automation.
Short answer
- You want test environments on their own hostnames → Bybit. OKX demo REST
shares the production host and switches with
x-simulated-trading: 1. - You want a timestamp tolerance in seconds, not milliseconds → OKX
allows 30 seconds either way; Bybit allows
recv_windowbehind (default 5000 ms) and under 1000 ms ahead. - You want isolated and cross to coexist in one account → OKX keeps isolated positions segregated from the cross account. Under Bybit’s Unified Trading Account, the margin mode is one setting for the whole account.
- You want official SDKs beyond Python → Bybit’s guide lists eight languages; the OKX V5 docs link a Python SDK, and we did not find others linked there.
What they have in common
- HMAC-SHA256 signing with a server-time endpoint (
GET /v5/market/time,GET /api/v5/public/time). - Private rate limits counted per account (Bybit per UID, OKX per User ID), with batch endpoints limited separately from single-order ones.
- One-way and hedge position modes, with a side parameter required in hedge.
- Portfolio margin restricted to one-way (Bybit) or net (OKX) mode.
- Error codes in the body, often under HTTP 200.
Where they actually differ
Credentials and signing
| Bybit | OKX | |
|---|---|---|
| Credentials | Key + secret (or RSA key pair) | Key + secret + passphrase |
| Headers | X-BAPI-API-KEY, X-BAPI-TIMESTAMP, X-BAPI-SIGN, X-BAPI-RECV-WINDOW | OK-ACCESS-KEY, OK-ACCESS-SIGN, OK-ACCESS-TIMESTAMP, OK-ACCESS-PASSPHRASE |
| Signed string | timestamp + api_key + recv_window + queryString or + jsonBodyString | timestamp + method + requestPath + body |
| HMAC output | Lowercase hex | Base64 |
| Asymmetric option | Self-generated RSA; Bybit holds only the public key | — (HMAC-SHA256 documented) |
| Bad signature | 10004 | 50113 “Invalid signature.” |
OKX signs the method and path (GET query parameters belong to
requestPath); Bybit signs your key and the receive window. The OKX passphrase
is stored only as a salted hash and cannot be recovered; 50104 and 50105
cover a missing or wrong one. See the OKX API passphrase and
API signature methods compared.
Timestamps
Bybit wants Unix milliseconds and applies
server_time - recv_window <= timestamp < server_time + 1000, failing with
10002. OKX wants ISO 8601 UTC with milliseconds and rejects anything more
than 30 seconds from server time with 50102, or a malformed value with
50112. OKX names local timezone offset as the most common cause of 50102,
and its WebSocket login uses epoch seconds instead. See
clock sync and timestamps.
Permissions and IP binding
OKX documents Read, Trade and Withdraw permissions in any combination. IP binding is recommended but optional; unbound keys with trade or withdraw permission expire after a period of inactivity (window on OKX’s key-creation page).
For Bybit we can confirm IP binding exists (10010) and that a missing
permission returns 10005, but we have not verified its permission scopes or
whether IP binding is mandatory for any, so we compare only the error codes:
| Failure | Bybit | OKX |
|---|---|---|
| Key not recognised / wrong environment | 10003 | 50111, 50101 |
| IP not bound to the key | 10010 | 50110 |
| Key lacks the permission | 10005 | 50120 |
Bybit’s 10003 has a trap: over REST it means an invalid key or environment
mismatch, but on the WebSocket order-entry channel it means too many sessions.
See Bybit API error 10003.
Rate-limit models
Bybit runs two layers: a per-IP HTTP limit (HTTP 403 “access too
frequent”) and a per-UID, per-endpoint limit on a rolling per-second window
(10006), reported in X-Bapi-Limit* headers on every response. Batch
endpoints consume one unit per order; overflow orders fail, the rest succeed.
OKX sets limits per endpoint. Private REST is per User ID, public REST per
IP. Trading endpoints are limited per instrument ID and shared between REST
and WebSocket, and a sub-account-level order limit runs in parallel (50061).
Breaches return 50011, listed with both HTTP 200 and 429.
Bybit budgets by endpoint, OKX additionally by instrument, so a bot trading many symbols hits the two walls in different places. See rate-limit models compared.
Test and demo environments
Bybit gives environments their own hosts: api-testnet.bybit.com and
api-demo.bybit.com (demo key created on Production in Demo Trading mode).
10003 lists four environments, and a key works only in its own.
OKX demo REST uses openapi.okx.com with x-simulated-trading: 1; demo
WebSocket has its own host, wspap.okx.com. A dropped header sends a REST
request to production. OKX’s code for an environment mismatch is 50101. See
the Bybit testnet guide and
testnet environments compared.
Account modes and liquidation scope
Bybit. The classic account is now unavailable; accounts are on the Unified
Trading Account, reported by unifiedMarginStatus. Under UTA, “you cannot
choose different margin modes for individual trading pairs” — the margin mode,
set via /v5/account/set-margin-mode, applies to the whole account:
| Bybit margin mode | API value | Liquidation decided |
|---|---|---|
| Isolated | ISOLATED_MARGIN | Per position, at its liquidation price |
| Cross (default) | REGULAR_MARGIN | Per account, when Account MMR reaches 100% |
| Portfolio | PORTFOLIO_MARGIN | Per account, when Account MMR reaches 100% |
OKX. Account mode (acctLv) and isolated/cross are separate layers.
Isolated risk is per position and segregated from cross. What “cross” covers
depends on the account mode:
OKX account mode (acctLv) | Cross liquidation scope |
|---|---|
| 1 Spot | No perpetuals, so no perp liquidation |
| 2 Futures | Per margin currency — all assets in that currency |
| 3 Multi-currency margin | Account-wide, in USD — all cross collateral |
| 4 Portfolio margin | Account-level trigger; maintenance margin from stress-test losses per risk unit |
So “cross” on Bybit means the whole account; in OKX Futures mode, one margin
currency. Both treat the reported cross liquidation price as an estimate:
Bybit’s liqPrice is “an estimated price” (empty for portfolio margin), and
OKX’s liqPx “can change quickly”. See
isolated vs cross margin and
what a unified trading account is.
Position mode parameters
| Bybit | OKX | |
|---|---|---|
| Switch | POST /v5/position/switch-mode, mode 0/3, per symbol or settle coin | POST /api/v5/account/set-position-mode, posMode net_mode/long_short_mode |
| Order field | positionIdx 0, or 1 buy / 2 sell in hedge | posSide net, or long/short |
| Switch blocked | 110028 open orders, 110024 open position | — |
| Missing side | — | 51000 |
Dashes are gaps in what we verified, not claims of absence. See hedge mode.
Error envelopes
Bybit returns retCode, retMsg, result, retExtInfo, time; 10xxx
codes cover request, auth and limits, 110xxx derivatives and positions.
Several balance codes read almost identically (110004 and 110045 both say
“Wallet balance is insufficient”), so log the number.
OKX codes run 50000–59999 with optional sub-codes such as 51008_1000. Auth
errors use HTTP 401 (50115 uses 405); many trade errors return HTTP 200, with
per-item results in sCode and sMsg. See
OKX API error 50113.
Regional access
Bybit’s guide says IPs in the US or Mainland China are restricted and receive
HTTP 403. OKX routes US and Australian users registered on app.okx.com to
us.okx.com, and EU users registered on my.okx.com to eea.okx.com. Check
each venue’s own terms for where it serves.
Which to pick
| Your situation | Lean toward | Why |
|---|---|---|
| You want environment mistakes to fail authentication | Bybit | Separate testnet and demo hosts |
| You want isolated and cross positions in the same account | OKX | Isolated is segregated from cross; Bybit UTA’s margin mode is account-wide |
| You want cross risk limited to one margin currency | OKX (Futures mode) | Cross is assessed per margin currency there |
| You pace by endpoint and read budget from headers | Bybit | X-Bapi-Limit-Status per endpoint |
| You need an official SDK outside Python | Bybit | Eight official languages listed |
Can you use both
Yes. Make the account mode explicit: read the Bybit margin mode and the OKX
acctLv at startup and refuse to trade if either differs from what the
strategy assumes. A unified library handles signing, not the account model; see getting started with CCXT.
FAQ
Does Bybit have an equivalent of the OKX passphrase?
No passphrase appears in Bybit’s authentication headers: it uses a key and
secret with HMAC, or a self-generated RSA pair where Bybit holds only the public
key. OKX requires OK-ACCESS-PASSPHRASE on every private request and cannot
recover a lost passphrase.
Is Bybit cross margin the same as OKX cross margin?
They differ in scope. Under Bybit’s Unified Trading Account, cross margin is assessed for the whole account through Account MMR. On OKX, cross in Futures mode is assessed per margin currency, while Multi-currency margin mode assesses the whole account in USD.
Why do both Bybit and OKX return errors with HTTP 200?
Both put the result in the response body — retCode on Bybit, code or
sCode on OKX — and many business errors arrive with HTTP 200. Status codes
are used mainly for auth and rate-limit conditions, so a client must parse the
body on every response.
Which Bybit and OKX codes mean the IP is not whitelisted?
Bybit returns 10010 “Unmatched IP, please check your API key’s bound IP
addresses.” OKX returns 50110, saying your IP is not in the key’s IP
whitelist. Both mean the request came from an address the key is not bound to.