API Authorization
Overview
Taker API uses API Key + Secret signature-based authentication. Developers must sign each request using their API Key and API Secret. The signature is generated by concatenating the request method, request path, timestamp, and request parameters/body with | delimiter, then applying the HMAC-SHA256 hash algorithm. The signature and related metadata are included in the request headers. The server validates the signature, authenticates the user, and authorizes before processing the request.
Authentication Flow
Each request must include:
- API Key
- Timestamp
- Signature calculated using API Secret and request content
The API validates:
- API Key is valid and active
- Signature matches the request content
- Timestamp is within allowed range (default tolerance ±5 minutes)
If any validation fails, the request returns an error code, such as:
{"code":10010008,"message":"Signature verification failed"}Required Request Headers
All authenticated API requests must include the following custom headers:
| Header Name | Example Value | Description |
|---|---|---|
X-API-Key | A1B2C3D4E5F6... | Your public API key |
X-API-Signature | a8f9c3e... | HMAC-SHA256 generated signature |
X-API-Timestamp | 1715100000000 | Current UNIX timestamp in milliseconds |
Optional (recommended for tracking):
| Header Name | Example Value | Description |
|---|---|---|
X-REQUEST-ID | uuid-string | Client-defined request ID for debugging and log correlation |
Signature Generation Steps
Use uppercase HTTP request method (e.g.,
POST).Concatenate with
|the API path (without domain and protocol, must start with/, e.g.,/api/v1/orders).Append the UNIX timestamp in milliseconds.
Append the request parameters:
- GET requests: Use
key=valueconcatenated query parameters (without?), empty string if none. Note: Do not change the order of parameters, ensure the signed and requested parameters are consistent. - Non-GET requests: Use raw JSON string as body, empty string if none. Note: Ensure the request body and signature are consistent, do not change due to formatting, causing the request and signature to be different.
- GET requests: Use
Final signature string format:
{request_method}|{request_path}|{timestamp}|{query_string_or_request_body}Use API Secret to encrypt this signature string with HMAC-SHA256.
Base64 encode the result.
Add the following headers to the request:
X-API-KeyX-API-TimestampX-API-Signature
Example (Signature String Construction):
POST|/api/v1/orders/lock|1746774142003|{"order_hash":"0x1234..."}Final signature:
Base64(HMAC-SHA256(signature_string, API_Secret))Code Examples
import requests
import hmac
import hashlib
import base64
import time
class TakerApiClient:
def __init__(self, api_key, api_secret, base_url):
self.api_key = api_key
self.api_secret = api_secret
self.base_url = base_url
def send_request(self, method, path, query_string='', body=''):
timestamp = int(time.time() * 1000) # Milliseconds
signature_string = self.build_signature_string(method, path, timestamp, query_string, body)
signature = self.generate_signature(signature_string, self.api_secret)
url = self.base_url + path
if query_string:
url += '?' + query_string
headers = {
'X-API-Key': self.api_key,
'X-API-Timestamp': str(timestamp),
'X-API-Signature': signature,
'Content-Type': 'application/json'
}
if method.upper() == 'GET':
response = requests.get(url, headers=headers)
else:
response = requests.request(method.upper(), url, headers=headers, data=body)
return response.text
def build_signature_string(self, method, path, timestamp, query_string, body):
signature_string = f"{method.upper()}|{path}|{timestamp}"
if method.upper() == 'GET':
signature_string += f"|{query_string}"
else:
signature_string += f"|{body}"
return signature_string
def generate_signature(self, data, secret):
key = secret.encode('utf-8')
message = data.encode('utf-8')
hmac_obj = hmac.new(key, message, hashlib.sha256)
return base64.b64encode(hmac_obj.digest()).decode('utf-8')
# Usage example
api_key = 'your_api_key_here'
api_secret = 'your_api_secret_here'
base_url = '{API_BASE_URL}'
client = TakerApiClient(api_key, api_secret, base_url)
# Lock order example
lock_body = '{"order_hash":"0x1234...","lock_duration":300}'
response = client.send_request('POST', '/api/v1/orders/lock', body=lock_body)
print('Lock Response:', response)
# Query orders example
query_response = client.send_request('GET', '/api/v1/orders', 'status=locked&page=1&page_size=20')
print('Query Response:', query_response)Common Use Cases
Lock Order
curl -X POST "{API_BASE_URL}/api/v1/orders/lock" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-API-Timestamp: 1715100000000" \
-H "X-API-Signature: GENERATED_SIGNATURE" \
-H "Content-Type: application/json" \
-d '{"order_hash":"0x1234...","lock_duration":300}'Fill Order
curl -X POST "{API_BASE_URL}/api/v1/orders/fill" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-API-Timestamp: 1715100000000" \
-H "X-API-Signature: GENERATED_SIGNATURE" \
-H "Content-Type: application/json" \
-d '{"order_hash":"0x1234...","fill_quantity":"100"}'Query Orders
curl -X GET "{API_BASE_URL}/api/v1/orders?status=locked&page=1&page_size=20" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-API-Timestamp: 1715100000000" \
-H "X-API-Signature: GENERATED_SIGNATURE"Error Codes
| Code | Message | Description | Solution |
|---|---|---|---|
| 10010008 | Signature verification failed | Signature does not match | Check signature generation logic, ensure parameters are consistent |
| 10010009 | API key not found | API key does not exist | Verify API key is correct |
| 10010010 | API key expired | API key has expired | Contact administrator to renew API key |
| 10010011 | Timestamp expired | Request timestamp outside allowed range | Ensure system time is synchronized, regenerate timestamp |
| 10010012 | Missing required header | Missing authentication header | Ensure all required headers are included |
| 401 | Unauthorized | Authentication failed | Check API key and signature |
| 403 | Forbidden | No permission to access resource | Contact administrator to verify permissions |
Security Best Practices
For API Key Management
Secure Storage
- Never hardcode API keys in source code
- Use environment variables or secure configuration management
- Rotate API keys regularly
Access Control
- Use different API keys for different environments (dev, staging, prod)
- Implement IP whitelist if possible
- Monitor API key usage and set up alerts
Secret Protection
- Never expose API secret in client-side code
- Never log API secret in application logs
- Use HTTPS for all API communications
For Signature Generation
Timestamp Validation
- Ensure system time is synchronized with NTP server
- Handle clock skew appropriately
- Regenerate signature for retry requests
Parameter Consistency
- Do not modify request parameters after signature generation
- Maintain parameter order for GET requests
- Avoid formatting JSON body after signature generation
Error Handling
- Implement exponential backoff for failed requests
- Log signature verification failures for debugging
- Do not retry with same signature if timestamp expired
Troubleshooting
Issue: Signature verification failed
Possible causes:
- Incorrect API secret
- Parameter order mismatch
- JSON body formatting differences
- Timestamp format incorrect
Solution:
- Verify API secret is correct
- Log the signature string before hashing
- Ensure request body matches signed body exactly
- Use millisecond timestamp (not seconds)
Issue: Timestamp expired
Possible causes:
- System clock not synchronized
- Request took too long to send
- Reusing old signature
Solution:
- Synchronize system time with NTP
- Generate new signature for each request
- Reduce network latency
Issue: API key not found
Possible causes:
- Incorrect API key
- API key deleted or expired
- Wrong environment
Solution:
- Verify API key from admin panel
- Check if using correct environment (test vs prod)
- Contact administrator if key is missing