What is HMAC request signing in exchange APIs?
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.
HMAC request signing is the scheme in which your client computes a keyed hash of the request — usually HMAC-SHA256 — using your API secret, sends that hash with the request, and the exchange recomputes the same hash with its own copy of the secret to confirm the request came from your key and was not altered.
The secret itself never travels. What travels is proof that whoever built the request held it. This page explains what gets signed, what a valid signature does and does not prove, how the major venues differ, and why signing errors are almost always about the inputs rather than the cryptography.
Why this matters now
Signing is the step every private request goes through, and it is where most authentication failures come from — including ones that look like permission or key problems. Understanding the mechanism turns an opaque “invalid signature” into a short list of things that could differ.
It also matters for a less obvious reason if a model is involved: the signature is the point at which a request becomes authorised. Anything that can reach the signing step with your secret can produce a request the exchange will accept as yours. Where signing happens, and what sits before it, is a security decision.
How it actually works
- Build the pre-hash string. The venue defines which parts of the request go into it and in what order — typically a timestamp plus some combination of the method, path, query string and body.
- Compute the HMAC of that string using your API secret as the key.
- Encode the result in the form the venue expects. OKX, for example, requires Base64.
- Send it alongside your API key identifier and the timestamp, in headers or parameters as the venue specifies.
- The venue rebuilds the pre-hash string from what it received, computes the HMAC with its stored copy of your secret, and compares. It also checks the timestamp against its acceptance window.
The exchange does not verify what you meant to send. It verifies what arrived. If one byte of the signed material differs between what you hashed and what the venue reconstructs — a reordered query parameter, a re-serialised JSON body, a second timestamp — the hashes differ and the request is rejected.
What a valid signature proves, and what it does not
| Proves | Does not prove |
|---|---|
| The sender holds the secret for this key | That the sender is you — a leaked secret signs perfectly |
| The signed parts were not altered in transit | Anything about parts outside the pre-hash |
| The request is recent, because the timestamp is signed | That the request is sensible, sized correctly, or intended |
| Confidentiality — TLS does that, not the signature |
The timestamp row is why clock problems surface as authentication failures. Because the timestamp is inside the signed material, it cannot be edited in transit, and the venue can reject stale or future-dated requests. See clock sync and timestamp errors, and timestamp tolerance compared for the windows side by side.
How the major venues differ
| Venue | What is signed | Algorithms documented | Where it goes |
|---|---|---|---|
| Binance (spot) | Query string concatenated with the HTTP body; must include timestamp | HMAC-SHA256, RSA, Ed25519 | signature parameter; key in X-MBX-APIKEY |
| Bybit (V5) | timestamp + api_key + recv_window + queryString (GET) or + jsonBodyString (POST) | HMAC_SHA256, RSA_SHA256 | X-BAPI-SIGN header |
| OKX (V5) | timestamp + method + requestPath + body, Base64-encoded | HMAC-SHA256 | OK-ACCESS-SIGN header, plus key, timestamp and passphrase headers |
| Hyperliquid | No HMAC — actions are signed as EIP-712 typed data with an Ethereum key | — | See Hyperliquid’s signing docs |
None of the three HMAC constructions is compatible with the others. A signer ported from OKX includes a method and path that Bybit does not sign; a signer ported from Binance omits the timestamp and key that Bybit does. Each produces a well-formed signature the destination rejects. API signature methods compared goes through the differences in detail.
HMAC vs asymmetric signing
HMAC is symmetric: the exchange holds a copy of the same secret you sign with. That is simple and fast, and it means the secret exists in two places — yours and the venue’s.
Asymmetric schemes such as RSA and Ed25519 split the roles. You sign with a private key; the venue verifies with a public key and never holds anything that can create a signature. Binance supports both kinds, documents Ed25519 as recommended for best performance, and has tightened the rules for HMAC keys without IP restriction — recommending they carry no permission beyond reading, and pointing users to IP restriction or self-generated Ed25519 or RSA keys to enable more. Bybit documents RSA_SHA256 alongside HMAC.
Hyperliquid sits further along the same line: there is no API secret at all, only a wallet key that signs typed data, and delegation happens by approving a separate signing wallet — see Hyperliquid API setup.
Why signatures fail
Almost never because HMAC is computed wrongly. Almost always because an input differs:
- Signed and sent diverge. The query string or body was serialised once for signing and again for sending.
- Two timestamps. One generated for the signature, another for the header.
- Wrong encoding or case. Binance documents HMAC signatures as case-insensitive but RSA and Ed25519 signatures as case-sensitive; OKX expects Base64.
- Wrong secret. On OKX, swapping the passphrase and the secret is a common version — see OKX API passphrase.
- A construction ported from another venue.
Binance reports a mismatch as -1022 (“Signature for this request is not
valid.”). For OKX, 50113 is “Invalid signature.” in OKX’s own V5 error-code table
(HTTP 401). See
Binance API error -1022,
OKX API error 50113, and
authentication errors across exchanges.
Where the boundary should sit
- One function builds, signs and sends. Signing and sending should consume the same variables, so they cannot disagree.
- Log the pre-hash string, never the secret. The string contains nothing secret, and comparing it with what went on the wire resolves most failures in minutes.
- Keep the secret out of any model’s reach. A model should hand a proposed order to code that signs it; it should never see, hold or pass the secret.
- Approve before signing. Once a request is signed and sent, the exchange will treat it as yours. Any check you want to apply — size caps, a human approval — has to happen before this step.
FAQ
What is HMAC-SHA256 used for in exchange APIs?
It authenticates private requests. Your client hashes a venue-defined string built from the request, using your API secret as the key, and sends the result. The exchange recomputes the hash with its copy of the secret; if the two match, the request is accepted as coming from your key and unaltered in transit.
Is my API secret sent with each request?
No. Only the resulting signature is sent, alongside your API key identifier. The secret stays on your side, and the exchange uses its own stored copy to verify. That is why a leaked signature from one request cannot be reused for a different request, while a leaked secret can sign anything.
Why does my signature work on one exchange but not another?
Because each venue signs a different string. Binance signs the query string concatenated with the body; Bybit signs timestamp, key, receive window and the query string or body; OKX signs timestamp, method, path and body, then Base64-encodes it. Rebuild the construction from the target venue’s documentation rather than adapting code from another.
Is RSA or Ed25519 signing safer than HMAC?
It changes where the signing secret lives. With HMAC the exchange holds a copy of your secret; with RSA or Ed25519 it holds only a public key that cannot sign. Binance documents Ed25519 as recommended for best performance and restricts what unrestricted-IP HMAC keys can do. Whether to switch depends on your venue’s support and your client library.