Signing
To ensure the security of your account, all requests to private endpoints must be digitally signed. A signature is a cryptographic process that proves to QuBit that a request was genuinely sent by you (the holder of the Secret Key) and that its content has not been tampered with during transit.
💡 SDK Recommended
We strongly recommend using our official SDKs to interact with the API. The SDKs handle all the complex signing logic for you, which can significantly reduce development time and the possibility of errors.
If you need to implement the signing process yourself, please follow this guide carefully. An incorrect signature will result in an authentication failure (
401 Unauthorized), and debugging can be challenging due to the various potential causes of a signature mismatch.
Signing Process Overview
The QuBit signing process consists of the following three steps:
Construct the Prehash String
Compute the HMAC-SHA256 Hash using your Secret Key
Base64-Encode the Hash Result
Step 1: Construct the Prehash String
The prehash string (stringToSign) is a plain text string created by concatenating four components of your request in a strict order.
Concatenation Rule: timestamp + method + requestPath + body
timestamp(String):REST API: The ISO 8601 formatted UTC timestamp string you are sending in the
Qubit-Api-Timestampheader, e.g.,"2025-07-16T10:30:00.123Z".WebSocket Auth: The value of the
timestampfield in theargsof yourloginmessage.
method(String):REST API: The uppercase HTTP request method, e.g.,
"GET"or"POST".WebSocket Auth: The fixed value
"GET".
requestPath(String):REST API: The path of the request, excluding the domain and query parameters. For
https://api.qubit.com/api/v1/trade/order?a=1, therequestPathis"/api/v1/trade/order".WebSocket Auth: The fixed value
"/users/ws/auth".
body(String):For
GETorDELETErequests, thebodycomponent is an empty string"".For
POSTorPUTrequests, thebodyis the full, unmodified JSON request body string. If the request body is empty (e.g.,{}), thebodyis"{}".
Pseudocode Example (REST API):
Step 2: HMAC-SHA256 Hash
Use your Secret Key as the HMAC key to compute the HMAC-SHA256 hash of the prehash string (stringToSign).
Input:
stringToSign(from Step 1),Secret Key(the private key you received when creating the API Key)Algorithm: HMAC-SHA256
Output: A binary hash digest.
Step 3: Base64 Encoding
Take the binary hash digest generated in the previous step and encode it using standard Base64 encoding to get the final signature string.
This Base64-encoded string is the value you need to include in the Qubit-Api-Signature header of your request.
Common Errors & Debugging Tips
If your requests are consistently met with a 401 Unauthorized response with msg: "invalid signature", please check for these common mistakes:
Incorrect Prehash String (
stringToSign) Concatenation:Wrong Order: Ensure the strict order of
timestamp+method+requestPath+body.Extra Content in
requestPath: Make surerequestPathdoes not include the?and any subsequent query parameters.Body Mismatch:
For
POSTrequests, thebodystring used for signing must be byte-for-byte identical to the request body you actually send. An extra space or a different field order in the JSON will result in a different signature. It's recommended to generate the JSON string first, use it for signing, and then send that exact string as the request body.For
GETrequests, ensure thebodycomponent is an empty string"", notnullor{}.
Timestamp Issues:
Ensure the
timestampused for signing is exactly the same as the one sent in the request header.Ensure the timestamp is in UTC and formatted as ISO 8601, including milliseconds if your language/library supports it.
Encoding Problems:
Ensure all strings are UTF-8 encoded.
Make sure you are Base64-encoding the raw binary output of the HMAC-SHA256 function, not its hexadecimal (Hex) representation.
Debugging Suggestion: In your code, print the final, concatenated stringToSign before it's hashed. Then, use an online HMAC-SHA256 tool to manually compute the signature with your stringToSign and Secret Key. Base64-encode the raw output and see if it matches what your program generates.
Last updated