Learn / Exchange APIs

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 5011150115 here 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:

CodeMeaningProvenance
50111Invalid OK_ACCESS_KEY — the key itself is not recognisedCCXT mapping
50112Invalid OK_ACCESS_TIMESTAMPCCXT mapping
50113Invalid signatureCCXT mapping
50114Invalid authorizationCCXT mapping
50115Invalid request methodCCXT mapping
50102Timestamp differs from server time by more than 30 secondsOKX docs

All of 5011150115 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 50102 rather than 50113, 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

  1. Log the pre-hash string — the exact string being signed, not the secret.
  2. Log the outgoing URL, after the client has built it.
  3. Compare them character by character. Cause 1 becomes obvious instantly.
  4. Check the timestamp appears identically in the pre-hash and the header.
  5. Check x-simulated-trading if using demo credentials.
  6. 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.