Skip to main content
Olympex authenticates requests with an HMAC signature. You create an API account once, keep its three credentials on your server, and sign every request to a signed endpoint with four headers. You sign with the secret key but never send it. The signature binds each request to its method, path, query and body, the current time and a random nonce that the server rejects if it has seen it in the last 5 minutes, so each set of signed headers works once, for the one request you signed. Every endpoint lives under one base URL:
Requests and responses are JSON. Endpoints use GET, POST, PATCH and DELETE: POST and PATCH send a JSON body, and GET and DELETE send none. Send Content-Type: application/json on every request, including the public ones and those without a body. Without it, or with another type such as curl’s default application/x-www-form-urlencoded, a request with a body fails with 403 (Invalid body hash) on a signed endpoint or 400 (Invalid JSON body) on a public one.

Public and signed endpoints

One endpoint is public, POST /accounts. Every other endpoint is signed. A new API account can call the signed endpoints as soon as POST /accounts returns. There is no activation step. Limit orders and DCA strategies belong to the API key that created them. List endpoints return only yours, and an ID created with another API key returns 404 NOT_FOUND, as if it didn’t exist.

The three credentials

Keep them in the environment variables OLYMPEX_API_KEY_ID, OLYMPEX_SECRET_KEY and OLYMPEX_PASSPHRASE. The reference implementations and every example in these docs read those names. Credentials covers how Olympex stores each one and how you should.
Protect the passphrase like the secret key. It travels in x-passphrase on every signed request, so anything that records your request headers records it. Keep all three credentials on your server.

The four headers

Every signed request carries these headers, plus content-type: application/json: timestamp is the current Unix time in seconds, nonce is 24 new random hexadecimal characters, and bodyHash is the unpadded base64url SHA-256 of the exact body you send: the empty string for a GET or DELETE, which has no body. The method is uppercase. The path is the URL path you call, starting with /api/v1, without the query string. The canonical query is the query string with its parameters decoded, sorted by key and then by value, and percent-encoded again per RFC 3986, or the empty string when there is none. Headers signed for one request don’t work on another, and each nonce works once. Sign requests has the full algorithm and reference code.

How signing works

You never send the secret key. You hash the exact body you’re about to send (the empty string for a GET or DELETE) and sign that hash together with the method, the path, the query, the current time and a random nonce, with HMAC-SHA256 keyed with your secret key. Olympex rejects timestamps more than 300 seconds from its clock, looks up your account by API key ID, recomputes the signature over the request it received with the secret key it holds for your account, checks the passphrase, and rejects nonces it has already seen in the last 5 minutes. It then checks that the body it received matches the hash you signed.
1

Canonicalize the body

Serialize the JSON body with object keys sorted at every level and no whitespace. This string, bodyString, is exactly what you send. A GET or DELETE has no body, so its bodyString is the empty string.
2

Hash it

bodyHash is the SHA-256 of bodyString, encoded as unpadded base64url.
3

Build the message

Join OLPX-HMAC-SHA256-V2, the Unix time in seconds, 24 new random hexadecimal characters, the method in uppercase, the path (starting with /api/v1), the canonical query and bodyHash with newlines.
4

Sign and send

Send timestamp, nonce and bodyHash, joined with newlines, as standard base64 in x-value-info, and the lowercase hex HMAC-SHA256 of the message, keyed with your secret key, in x-signature. Add x-api-key-id and x-passphrase. Send bodyString as the body of a POST or PATCH, and no body with a GET or DELETE. Query parameters go in the URL, and you sign them.
Sign requests is the normative specification, with reference implementations in TypeScript, Python and bash, requests without a body, two known-answer vectors and a troubleshooting table.
No credentials yet? Create a test API key in one click, then try any signed endpoint from the API console. If your browser blocks either call, create the key from a terminal and send requests with Copy as cURL.

What this means for your integration

  • Sign on your server. Browser, mobile and desktop apps call your backend, and your backend calls Olympex.
  • Sign every attempt, retries included, right before you send it, on a server whose clock is synchronized with NTP. The server rejects a timestamp more than 300 seconds off and a nonce it has seen in the last 5 minutes, so stored headers stop working.
  • Treat signed headers as single-use credentials for the one request you signed them for: never log, store or share them.
  • Start from a reference implementation and test your signer against the known-answer vectors before you send real traffic.

Credentials

What the API key ID, secret key and passphrase are, and how to store them.

Sign requests

The algorithm, requests without a body, reference code, known-answer vectors and troubleshooting.

Errors and retries

The error envelope, gateway responses and what to retry.

Limits

Timestamp window, nonce reuse, timeouts, order allowances and value ranges.