Authentication Overview
The CRYPTOMENTS Open API uses HMAC-SHA256 signature authentication. Each request is signed with the API Key / Secret Key pair issued by the Partner Console. The server recomputes the signature with the same algorithm to verify the request's authenticity.
Authentication Headers
Include the following 3 headers on every authenticated request:
| Header | Type | Description | Example |
|---|---|---|---|
X-API-KEY |
String | API Key issued in the Partner Console | pk_live_a1b2c3d4e5f6... |
X-TIMESTAMP |
String (seconds) | Unix epoch of the request time (in seconds). Must be within 5 minutes of server time. | 1711785600 |
X-ACCESS-TOKEN |
String (Base64) | HMAC-SHA256 signature (Base64-encoded) | q/Ek3B9f2x... |
Additionally, every request must include the Content-Type: application/json header.
Signature Algorithm
Generate the signature in the following order:
Concatenate timestamp + "." + apiKey into a single string. HTTP method and body are not included in the signature.
Generate an HMAC-SHA256 hash using Secret Key as the key and message as the message.
Convert the resulting byte array to a Base64 string and set it as the X-ACCESS-TOKEN header.
// Signature formula message = timestamp + "." + apiKey accessToken = Base64(HMAC_SHA256(secretKey, message)) // Example timestamp = "1711785600" apiKey = "pk_live_a1b2c3d4e5f6" message = "1711785600" + "." + "pk_live_a1b2c3d4e5f6" = "1711785600.pk_live_a1b2c3d4e5f6" accessToken = Base64(HMAC_SHA256("sk_live_...", message)) = "q/Ek3B9f2xR7..." // Base64 string
Math.floor(Date.now() / 1000) or int(time.time()).
Code Examples
const crypto = require('crypto'); const API_KEY = 'pk_live_a1b2c3d4e5f6'; const SECRET_KEY = 'sk_live_x9y8z7w6v5u4'; async function callApi(method, path, body = null) { const timestamp = Math.floor(Date.now() / 1000).toString(); const message = timestamp + '.' + API_KEY; const accessToken = crypto .createHmac('sha256', SECRET_KEY) .update(message) .digest('base64'); const bodyStr = body ? JSON.stringify(body) : undefined; const res = await fetch(`https://api.cryptoments.cc${path}`, { method, headers: { 'X-API-KEY': API_KEY, 'X-TIMESTAMP': timestamp, 'X-ACCESS-TOKEN': accessToken, 'Content-Type': 'application/json', }, body: bodyStr, }); return res.json(); } // Example: create a deposit wallet const result = await callApi('POST', '/api/v1/users/deposit-wallet', { chainType: 'BSC', currencyType: 'USDT', partnerUserId: 'user_001', }); console.log(result); // → { success: true, data: { address: "0x...", chainType: "BSC", ... } }
import hmac, hashlib, base64, json, time, requests API_KEY = 'pk_live_a1b2c3d4e5f6' SECRET_KEY = 'sk_live_x9y8z7w6v5u4' BASE_URL = 'https://api.cryptoments.cc' def call_api(method, path, body=None): timestamp = str(int(time.time())) message = timestamp + '.' + API_KEY signature = hmac.new( SECRET_KEY.encode(), message.encode(), hashlib.sha256 ).digest() access_token = base64.b64encode(signature).decode() headers = { 'X-API-KEY': API_KEY, 'X-TIMESTAMP': timestamp, 'X-ACCESS-TOKEN': access_token, 'Content-Type': 'application/json', } body_str = json.dumps(body) if body else None resp = requests.request(method, BASE_URL + path, headers=headers, data=body_str) return resp.json() # Example: fetch partner balances (GET, no body) result = call_api('GET', '/api/v1/partner/balances') print(result) # Example: request a withdrawal (POST) result = call_api('POST', '/api/v1/users/withdrawal', { 'chainType': 'BSC', 'currencyType': 'USDT', 'toAddress': '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18', 'amount': '100.00', 'partnerUserId': 'user_001', })
# Generate accessToken (bash) TIMESTAMP=$(date +%s) MESSAGE="${TIMESTAMP}.pk_live_a1b2c3d4e5f6" ACCESS_TOKEN=$(echo -n "$MESSAGE" | openssl dgst -sha256 -hmac "sk_live_x9y8z7w6v5u4" -binary | base64) curl -X POST https://api.cryptoments.cc/api/v1/users/deposit-wallet \ -H "Content-Type: application/json" \ -H "X-API-KEY: pk_live_a1b2c3d4e5f6" \ -H "X-TIMESTAMP: ${TIMESTAMP}" \ -H "X-ACCESS-TOKEN: ${ACCESS_TOKEN}" \ -d '{"chainType":"BSC","currencyType":"USDT","partnerUserId":"user_001"}'
Authentication Errors
Authentication failures return HTTP 401. Common causes:
| Error code | Cause | Resolution |
|---|---|---|
1001 |
Invalid API Key | Verify the API Key in the Partner Console. Make sure it's not deactivated. |
1002 |
Signature mismatch | Verify message construction (timestamp + "." + apiKey). Check the Secret Key for typos. Confirm Base64 encoding. |
EXPIRE_ACCESS_TOKEN |
Timestamp expired (over 5 minutes) | Synchronize with server time. NTP recommended. |
1003 |
Inactive partner | Contact your administrator about the partner account status. |
Widget Token Authentication
The widget API (/widgets/api/*) authenticates with a Bearer token. Your server issues a token via POST /widgets/auth/token, and the client makes requests with the Authorization: Bearer {token} header.
/api/v1/* endpoints → X-ACCESS-TOKEN (server ↔ server)
/widgets/auth/token → issue token via X-SIGNATURE (server → CRYPTOMENTS)
/widgets/api/* endpoints → Authorization: Bearer {token} (client → CRYPTOMENTS)
Widget Token Signature
The token-issuance request (POST /widgets/auth/token) uses a different signature scheme than the server API:
| Header | Type | Description |
|---|---|---|
X-API-KEY |
String | Partner API Key |
X-TIMESTAMP |
String (seconds) | Unix epoch (seconds). Must be within 5 minutes of server time. |
X-SIGNATURE |
String (Hex) | HMAC-SHA256 signature (lowercase hex, 64 chars) |
// Widget token signature formula message = METHOD + PATH + TIMESTAMP signature = hex(HMAC_SHA256(secretKey, message)) // Example method = "POST" path = "/widgets/auth/token" timestamp = "1711785600" message = "POST" + "/widgets/auth/token" + "1711785600" = "POST/widgets/auth/token1711785600" signature = hex(HMAC_SHA256("sk_live_...", message)) = "a3f8b1c2d4e5..." // 64-char hex
/api/v1/*) uses X-ACCESS-TOKEN + Base64; widget token issuance uses X-SIGNATURE + Hex. Don't mix them up.
const crypto = require('crypto'); const API_KEY = 'pk_live_a1b2c3d4e5f6'; const SECRET_KEY = 'sk_live_x9y8z7w6v5u4'; async function getWidgetToken(partnerUserId, permissions) { const timestamp = Math.floor(Date.now() / 1000).toString(); const method = 'POST'; const path = '/widgets/auth/token'; // Signature: METHOD + PATH + TIMESTAMP → hex const message = method + path + timestamp; const signature = crypto .createHmac('sha256', SECRET_KEY) .update(message) .digest('hex'); const res = await fetch('https://api.cryptoments.cc/widgets/auth/token', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-KEY': API_KEY, 'X-TIMESTAMP': timestamp, 'X-SIGNATURE': signature, }, body: JSON.stringify({ partnerUserId, permissions: permissions || ['DEPOSIT', 'WITHDRAWAL', 'BALANCE'], }), }); return res.json(); } // Example const token = await getWidgetToken('user_001'); console.log(token.accessToken); // → Send to the client; use as Authorization: Bearer {token}
Calling the Widget API (Bearer Token)
Use the issued token as the Authorization: Bearer {accessToken} header to call the widget API.
// accessToken issued by the server const accessToken = 'eyJhbG...'; // Use Bearer token when calling the widget API const res = await fetch('https://api.cryptoments.cc/widgets/api/balances', { method: 'GET', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, }); const data = await res.json(); console.log(data); // → { success: true, data: [...] }
CryptoPaymentsWidget) handles token issuance and Bearer-header setup automatically. The code above is only needed if you call the API directly.