Skip to Content
🚀 Spot APIAuthentication

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:

HeaderTypeDescription
X-BT-APIKEYStringYour API Key
X-BT-SIGNStringRequest signature
X-BT-TSLongRequest timestamp (milliseconds)
X-BT-NONCEStringRandom 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:

  1. Sort by key in ascending dictionary order
  2. Parameters with the same key are sorted by value in ascending dictionary order
  3. Array parameters are sorted by index order
2. Parameter Concatenation Rules

URL Parameters

  1. Include all parameters after the question mark (?).
  2. Sort keys in dictionary order and concatenate.
  3. Filter out empty arrays, null, and empty strings.
  4. Example: param1=value1&param2=value2.

Body Parameters

  1. JSON objects must be flattened to query string format.
  2. Arrays must be converted to key[index]=value format.
  3. Nested objects use dot (.) to represent hierarchy.
  4. Sort keys in dictionary order and concatenate.
  5. Filter out empty arrays, null, and empty strings.

Important Notes

  1. GET requests only use urlQuery parameters, POST requests use body parameters, ignoring url parameters.
  2. Must include timestamp and nonce parameters.
  3. Parameters are connected with &.
  4. For GET requests without parameters, the signature raw string starts with &.
&timestamp=1752647583398&nonce=e4c5e38c57a741f6a4658713
  1. For requests with parameters, the signature raw string starts with parameters
name=andy&timestamp=1752647583398&nonce=e4c5e38c57a741f6a4658713
3. 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=3

Final Signature String:

a=2&b=1&c=3&timestamp=1752647583398&nonce=e4c5e38c57a741f6a4658713
Example 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&timestamp=1752647583398&nonce=e4c5e38c57a741f6a4658713
Example 3: GET Request

URL Parameters:

categories=homeConfig,appConfig&a=2&a=1&c=1&d=123

After Sorting:

a[0]=1&a[1]=2&c=1&categories=homeConfig,appConfig&d=123
Example 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}&timestamp=${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

  1. Timestamp: The difference between server time and client time cannot exceed 5 minutes
  2. Random String: Each request must use a different nonce
  3. Parameter Encoding: All parameter values need to be URL encoded
  4. Signature Verification: The server will verify the correctness and timeliness of the signature
  5. 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

Last updated on: