OKX API error 50113 "Invalid Sign"
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.
OKX 50113 means the OK-ACCESS-SIGN header you sent does not match the
signature OKX computed for the same request. It typically comes back with HTTP
401, alongside the message "Invalid Sign".
A note on sources. OKX’s published V5 error list could not be retrieved while researching this, so the descriptions of
50111–50115here come from CCXT’s error mapping, not from OKX’s own documentation. They are widely used and consistent with reported behaviour, but they are not OKX’s wording. Treat them accordingly.
The neighbouring codes
Worth ruling out first, because they point at different problems:
| Code | Meaning | Provenance |
|---|---|---|
50111 | Invalid OK_ACCESS_KEY — the key itself is not recognised | CCXT mapping |
50112 | Invalid OK_ACCESS_TIMESTAMP | CCXT mapping |
50113 | Invalid signature | CCXT mapping |
50114 | Invalid authorization | CCXT mapping |
50115 | Invalid request method | CCXT mapping |
50102 | Timestamp differs from server time by more than 30 seconds | OKX docs |
All of 50111–50115 are classified as AuthenticationError in CCXT.
If you are getting 50111, the key string is the problem, not your signing —
check for whitespace or a newline from copy-paste, and check you have not
swapped the key with the passphrase. If you are getting 50102, it is a clock
problem.
The construction
OKX signs:
timestamp + method + requestPath + body
with HMAC-SHA256 using the secret key, Base64-encoded. Their example:
sign = CryptoJS.enc.Base64.stringify(
CryptoJS.HmacSHA256(
timestamp + 'GET' + '/api/v5/account/balance?ccy=BTC',
SecretKey
)
)
Almost every 50113 is one of the components being subtly different from what
went on the wire.
Five causes, in order
1. Query-string mismatch between signed and sent
This is the one that produces the maddening version of the bug: some calls succeed and others fail.
The requestPath in the pre-hash must include the query string exactly as
requested — same parameter order, same encoding. If you build the signed path
from a dictionary and the actual URL from a different serialisation, they can
differ in ordering or in how characters are escaped. Parameterless endpoints
work fine; parameterised ones fail.
The diagnostic: if failures are endpoint-specific rather than universal, this is
almost certainly it. Reported cases follow exactly this shape — some calls going
through while a specific endpoint consistently returns
{"msg":"Invalid Sign","code":"50113"}.
Fix: build the URL string once and sign that exact string. Never construct the signed path and the requested path separately.
2. Body mismatch
For POST, the body in the pre-hash must be the exact raw JSON string sent — same key order, same whitespace, same escaping. Serialising twice can produce two different strings.
For GET, the body is the empty string, not {} and not null.
Fix: serialise the body once into a variable, sign that variable, send that variable.
3. Timestamp problems
Three distinct failures wear this hat:
- Format. ISO 8601 UTC with milliseconds, e.g.
2020-12-08T09:08:57.715Z. No milliseconds, or a local timezone, fails. - Two different values. Generating the timestamp once for the signature and again for the header produces a mismatch. Generate once, use twice.
- Drift. If it is more than 30 seconds off you get
50102rather than50113, which is at least a clearer signal.
4. Demo versus production
Demo trading requires x-simulated-trading: 1 on the same hostname as
production. Using demo credentials without it reaches production, where the key
does not exist — and surfaces as an authentication failure rather than an
environment one.
Because the error points at your credentials, this sends people debugging the signature when the problem is a missing header. Check the header before you audit the signing code.
5. Wrong domain
Signing for okx.com while calling a legacy okex.com host. Also relevant if
you are on a regional endpoint — us.okx.com for US and AU users,
eea.okx.com for EU users.
How to debug it in five minutes
- Log the pre-hash string — the exact string being signed, not the secret.
- Log the outgoing URL, after the client has built it.
- Compare them character by character. Cause 1 becomes obvious instantly.
- Check the timestamp appears identically in the pre-hash and the header.
- Check
x-simulated-tradingif using demo credentials. - Only then start reading your HMAC code.
Most people do step 6 first and spend an hour there. The signing is rarely wrong; the inputs usually are.
Preventing it
- One function builds the request, signs it, and sends it. Signing and sending should never be able to disagree, because they consume the same values.
- Sign the serialised body variable, never a re-serialisation.
- Generate the timestamp once per request.
- Log the pre-hash string at debug level and leave it in. It is not sensitive — it contains no secret — and it turns this class of bug into a five-minute diagnosis permanently.
FAQ
Why do some OKX requests work and others return 50113?
Almost always a query-string mismatch between the path you signed and the path you requested — differing parameter order or encoding. Parameterless endpoints succeed because there is nothing to differ; parameterised ones fail. Build the URL once and sign that exact string.
Is 50113 a problem with my API key?
No, that is 50111 (invalid OK_ACCESS_KEY) in CCXT’s mapping. 50113 means
the key was recognised and the signature did not match — the difference is worth
noting because it points you at your request construction rather than your
credentials.
Could this be the passphrase?
Indirectly. The passphrase is sent as its own header rather than being part of the signature, so a wrong passphrase is not literally a signing failure — but swapping the passphrase and the secret means you are signing with the wrong material, which produces exactly this. It is worth a look given OKX is the only major venue with a third credential.
Does the demo trading header affect the signature?
No — x-simulated-trading is not part of the pre-hash string. But omitting it
sends demo credentials to production, where the key is unknown, and the
resulting authentication error can be mistaken for a signing failure. Check it
before auditing your HMAC code.