Authentication & Security
📋 Table of Contents
🔐 Authentication Requirements
Create API
Before using the API, you need to go to Bittap Website - Personal Center - API Management or Bittap App - Personal Center - API Management to create one. After creation, please keep your API Key and API Secret secure. For security reasons, please set up an IP whitelist when creating the API. Do not disclose your API Key / Secret Key to third parties. If compromised, please generate a new API immediately.
Permission Settings
Newly created APIs have no permissions by default. You need to manually enable Spot / Futures API permissions.
Required Headers
All authenticated endpoints must include the following headers:
| Header | Type | Description |
|---|---|---|
| X-BT-APIKEY | String | Your API Key |
| X-BT-SIGN | String | Request signature |
| X-BT-TS | Long | Request timestamp (milliseconds) |
| X-BT-NONCE | String | Random string |
Signature Parameters
Signature calculation requires the following parameters:
- timestamp: Current timestamp (milliseconds)
- nonce: Random string, recommend using UUID
- appSecret: Your API Secret
🔑 Signature Rules
1. Parameter Sorting Rules
All parameters are sorted according to the following rules:
- Sort by key in ascending dictionary order
- Parameters with the same key are sorted by value in ascending dictionary order
- Array parameters are sorted by index order
2. Parameter Concatenation Rules
URL Parameters
- Include all parameters after the question mark (?).
- Sort keys in dictionary order and concatenate.
- Filter out empty arrays, null, and empty strings.
- Example: param1=value1¶m2=value2.
Body Parameters
- JSON objects must be flattened to query string format.
- Arrays must be converted to key[index]=value format.
- Nested objects use dot (.) to represent hierarchy.
- Sort keys in dictionary order and concatenate.
- Filter out empty arrays, null, and empty strings.
Important Notes
- GET requests only use urlQuery parameters, POST requests use body parameters, ignoring url parameters.
- Must include timestamp and nonce parameters.
- Parameters are connected with &.
- For GET requests without parameters, the signature raw string starts with &.
×tamp=1752647583398&nonce=e4c5e38c57a741f6a4658713- For requests with parameters, the signature raw string starts with parameters
name=andy×tamp=1752647583398&nonce=e4c5e38c57a741f6a46587133. Special Processing Rules
- Nested Objects: Use dot notation, e.g.,
user.name=John - Arrays: Use square bracket indexing, e.g.,
hobbies[0]=reading - Empty Values: Skip null and empty strings
- Boolean Values: Convert to strings
4. Signature Calculation
Use HMAC-SHA256 algorithm to calculate signature:
signature = HMAC-SHA256(data, appSecret)Where data is the sorted and concatenated parameter string.
📝 Signature Examples
Example 1: Simple Parameters
Request Parameters:
{
"a": 2,
"b": 1,
"c": 3
}Sorted Concatenation:
a=2&b=1&c=3Final Signature String:
a=2&b=1&c=3×tamp=1752647583398&nonce=e4c5e38c57a741f6a4658713Example 2: Nested Objects
Request Parameters:
{
"a": [
{"b": 4, "c": 3},
{"x": 8, "y": 9}
],
"b": {
"data": {
"aa": [3, 2, 1]
},
"a": 2,
"z": 1
}
}After Sorting and Concatenation:
a[0].b=4&a[0].c=3&a[3].x=8&a[3].y=9&b.a=2&b.data.aa[0]=3&b.data.aa[1]=2&b.data.aa[2]=1&b.z=1×tamp=1752647583398&nonce=e4c5e38c57a741f6a4658713Example 3: GET Request
URL Parameters:
categories=homeConfig,appConfig&a=2&a=1&c=1&d=123After Sorting:
a[0]=1&a[1]=2&c=1&categories=homeConfig,appConfig&d=123Example 4: Array Request Body
Request Body:
[{"key1":"xxx","key2":"xx"}]After Conversion:
[0].key1=xxx&[0].key2=xx⚙️ Signature Calculation Steps
Step 1: Prepare Parameters
const timestamp = Date.now();
const nonce = generateNonce();
const params = {
symbol: "BTC-USDT",
quantity: 0.001,
price: 50000
};Step 2: Flatten Object
function flattenObject(obj, parentKey = '', result = {}) {
for (const [key, value] of Object.entries(obj)) {
const currentKey = parentKey ? `${parentKey}.${key}` : key;
if (value == null) continue;
if (Array.isArray(value)) {
value.forEach((item, index) => {
if (item != null) {
const arrayKey = `${currentKey}[${index}]`;
if (typeof item === 'object') {
flattenObject(item, arrayKey, result);
} else {
result[arrayKey] = item.toString();
}
}
});
} else if (typeof value === 'object') {
flattenObject(value, currentKey, result);
} else {
result[currentKey] = value.toString();
}
}
return result;
}Step 3: Sort Parameters
const flattened = flattenObject(params);
const sortedParams = Object.entries(flattened)
.sort((a, b) => a[0].localeCompare(b[0]))
.map(([key, value]) => `${key}=${value}`)
.join('&');Step 4: Add Required Parameters
const signData = `${sortedParams}×tamp=${timestamp}&nonce=${nonce}`;Step 5: Calculate Signature
const crypto = require('crypto');
function generateSignature(data, secret) {
const hmac = crypto.createHmac('sha256', secret);
hmac.update(data);
return hmac.digest('hex');
}
const signature = generateSignature(signData, appSecret);Step 6: Send Request
const response = await fetch('/api/endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-BT-APIKEY': apiKey,
'X-BT-SIGN': signature,
'X-BT-TS': timestamp,
'X-BT-NONCE': nonce
},
body: JSON.stringify(params)
});⚠️ Important Notes
- Timestamp: The difference between server time and client time cannot exceed 5 minutes
- Random String: Each request must use a different nonce
- Parameter Encoding: All parameter values need to be URL encoded
- Signature Verification: The server will verify the correctness and timeliness of the signature
- Secure Storage: Please keep your API Secret safe and do not disclose it to others
🔍 Frequently Asked Questions
Q: Why does signature verification fail?
A: Please check the following points:
- Whether parameter sorting is correct
- Whether the timestamp is within the valid period
- Whether nonce is reused
- Whether the API Secret is correct
Q: How to handle array parameters?
A: Array parameters need to be expanded in index order, e.g., items[0].price=100&items[1].price=200
Q: How to represent nested objects?
A: Use dot notation, e.g., user.profile.name=John