APIKEY header: a request carrying it is verified as HMAC and never retried
as a session, even if the signature is bad.
Session tokens
Exchange an email and password for a JWT:read, trade, and
withdraw. See Scopes for what each allows.
API keys
Mint a key from a session:secret is returned; store it then.
Keys carry exactly the scopes you name at mint time, capped at the minting
credential’s own scopes. A key never gains scopes later; mint a new key instead.
Scopes
Signing requests
Each HMAC request sends three headers:
The canonical message is:
PATH_AND_QUERYis the full request target including the query string:/rfq/quote?request_id=..., not/rfq/quote. Every GET endpoint takes its parameters from the query string, so they are inside the signature.BODYis the exact raw bytes you transmit. Sign the serialized string you send, not a re-serialization. For bodyless requests (GETs, DELETEs without a payload) the body segment is empty; the message still ends with the third\n.- The timestamp must be within ±30 seconds of server time (the deployment’s
AUTH_HMAC_TOLERANCE_SECS), which bounds the replay window.
Failure modes
A common cause of
401 is signing path while sending path?query, or letting
an HTTP client re-serialize the JSON body after signing.
Websocket tickets
Browsers cannot set headers on websocket upgrades, so socket connections authenticate with a short-lived ticket passed as a?ticket= query parameter:
POST /auth/ws-ticket: minted from a session; the ticket carriesread.POST /auth/ws-ticket/signed: HMAC-signed; the ticket inherits the key’s scopes.