Skip to main content
Hit trading bots use API key authentication with HMAC-SHA256 signatures. Public market data endpoints do not require authentication. Private trading endpoints and the /user WebSocket namespace require a trading API key, secret and passphrase.
Keep the API secret and passphrase out of source control and browser code. They are for server-side bots and services.

Credentials

Configure your bot with:
API key creation and key management are handled in the Hit app. These docs cover how to use an existing trading key from a programmatic client.

REST HMAC Headers

Every authenticated REST request must include: The signature message is:
Rules:
  • The four parts are joined with one newline character (\n, byte 0x0A) between each, and no newline follows body. A request without a body therefore ends with the newline that precedes the empty body.
  • method is uppercase, such as GET, POST or DELETE.
  • pathWithQuery includes /api/v1 and the query string exactly as sent, including the ?, and excludes the scheme and host. With no query string it is just the path.
  • body is the request body exactly as sent, byte for byte. Serialize it once into a variable, then sign and send that same string. Signing a separate re-serialization of your object produces a different signature.
  • Timestamps must be within 30 seconds of server time.

Legacy Signature Message

The original message is still accepted, with no retirement date set, so existing bots keep working unchanged:
It differs from the recommended message in two ways, not one. The parts are concatenated with no separator between them, and the parts themselves are different: path excludes the query string, and body is a re-serialization of the parsed JSON rather than the bytes you sent. Inserting newlines into a legacy message does not produce a valid recommended-form signature. For a GET request to /api/v1/markets/user-positions?id=abc&id=def with timestamp 1699123456789 and no body, the two forms sign: Each \n above is one newline character, not the two characters \ and n.

Where the Legacy Message Is Required

The recommended message is built from the raw request body the server captured. Where there is no raw body to capture, only the legacy message can match. Two cases matter in practice:
  • File uploads. A multipart/form-data request has no raw body available to the server, so a signature over the bytes you sent cannot match.
  • The /user WebSocket handshake. WebSocket authentication runs through a different service that builds only the concatenated message. See WebSocket Auth.

REST Signing Examples

WebSocket Auth

The /user Socket.IO namespace authenticates after connect with a user-connect message. The WebSocket signature message is different from REST:
The newline-separated REST message does not apply here. The handshake is verified by a different service, which builds only the concatenated message above, so signing the newline form fails authentication.
Payload:
The server responds on user-authenticated with { "success": true } or { "success": false, "error": "..." }.

Authentication Failures

A REST request whose trading API key fails authentication returns 401 with the message Authentication failed. The response does not say which check failed, so work through the causes in order:
  • A required header is missing.
  • The timestamp is outside the 30 second window, usually because the host clock has drifted.
  • The API key is unknown or no longer active.
  • The passphrase does not match the key.
  • The signature matches neither accepted message.
If your client branches on the older, more specific messages such as Invalid signature or Invalid passphrase, stop: those strings are no longer returned. The one exception is a key that could not be checked, which never gets a 401. A request whose key could not be checked against its current credentials, because the auth service could not be asked about it or did not answer with them or a refusal, returns 503 with error: CREDENTIAL_UNVERIFIABLE and no Retry-After header instead. Your key was not checked, so re-send the request, signed again with a fresh hit-timestamp, and keep the key.

Security Notes

  • Keep API secrets out of source control and client-side browser code.
  • Use separate keys for separate bots or services.
  • Deactivate unused or compromised keys immediately.
  • Keep host clocks synchronized; requests outside the timestamp window are rejected.