Skip to Content
📈 Futures APIAuthentication

Authentication and Security

📋 Table of Contents


🔐 Request 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 Request Headers

All authenticated endpoints must include the following request 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, recommended to use 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 dictionary order (ascending)
  2. Parameters with the same key are sorted by value in dictionary order (ascending)
  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 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 empty arrays, null, and empty strings.

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 indices, 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 and Concatenated:

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 } }

Sorted and Concatenated:

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

Sorted:

a[0]=1&a[1]=2&c=1&categories=homeConfig,appConfig&d=123
Example 4: Array Request Body

Request Body:

[{"key1":"xxx","key2":"xx"}]

Converted:

[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) });

⚠️ 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 validity of the signature
  5. Secure Storage: Please keep your API Secret safe and do not share it with others

🔍 Frequently Asked Questions

Q: Why does signature verification fail?

A: Please check the following:

  • Is parameter sorting correct?
  • Is the timestamp within the validity period?
  • Is nonce being reused?
  • Is the API Secret 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: