Skip to main content
Every request to the Omnibook API is authenticated. There is no anonymous access, even market data requires a key.
Using Python? Prefer the Python SDK, it signs requests and opens the WebSocket for you. The rest of this page is the raw HMAC contract (useful for other languages and for understanding what the SDK does).
You authenticate by signing each request with your API key’s secret and sending three headers. Nothing is sent as a bearer token, so intercepting a request does not give anyone your key.

Create an API key

  1. Sign in at omnibook.xyz.
  2. Go to Settings → API keys (/settings#keys).
  3. Click Create key, give it a name, and copy both values.
The secret is shown once and never again. Store it somewhere safe before you close the panel. Copy the API key too, you need both, and the list view does not show the secret again.If you lose a secret, revoke the key and create a new one. Revoking is immediate and irreversible.

The three headers

The canonical string

The signature covers the timestamp, method, request target and body, joined by newlines, with a trailing newline after the target:
Concretely, for GET /v1/portfolio/balance with no body:
Three things that catch people out:
  • The request target includes the query string. Sign /v1/rounds?limit=5, not /v1/rounds.
  • The body is the raw bytes you send, byte-for-byte. If you re-serialize your JSON between signing and sending, the signature breaks.
  • The signature covers the body, so you cannot sign once and replay with different parameters.
Hex-decode your secret before using it as the HMAC key.The secret is 32 random bytes, handed to you as 64 hex characters ([0-9a-f]). The HMAC key is those 32 raw bytes, not the 64-character string.Using the string directly produces a perfectly valid-looking signature and a permanent 401. This is the single most common integration bug.

Working examples

Clock skew

Your timestamp must be within ±5 seconds of the server’s clock. Outside that window the request is rejected as a replay, with the same 401 as a bad signature. If you see intermittent 401s that go away on retry, check your clock before you check your signing code.

Why a request failed

Every authentication failure returns the same response:
This is deliberate, an unknown API key, a bad signature, and a stale timestamp are indistinguishable, so probing tells an attacker nothing. Work through the list in order:
  1. Did you hex-decode the secret?
  2. Does the signed target include the query string?
  3. Is the signed body byte-identical to what you sent?
  4. Is your clock within 5 seconds?
  5. Is the key still live? A revoked key cannot be restored.

Complete script

Self-contained, paste your key and secret, then run:

Scopes

Keys carry scopes, and a bot key cannot withdraw funds. See API keys and scopes.