Generate API Signature
Sign every request.
The API signature is a Base64-encoded HMAC over a canonical request string, keyed with your integration's client secret. It proves both who you are and that the request hasn't been tampered with in transit.
Prerequisites
You'll need theseBuild the Signature
4 stepsConcatenate these six elements in order — no separators — to form the message that will be signed:
- 1BOM\ufeffByte Order Mark
- 2MethodPOST | GET | …HTTP method
- 3URLhttps://a-api.coinpayments.net/api/v2/…Full URL
- 4Client IDclientIdIntegration client id
- 5TimestampYYYY-MM-DDTHH:mm:ssUTC ISO-8601
- 6Payload{ "key": "value" }JSON body (or empty)
Compute an HMAC over the concatenated string using SHA-256 with your clientSecret as the key.
Encode the resulting digest in Base64. The signature is the final Base64 string.
Send the Base64 value as the X-CoinPayments-Signature header alongside the other two required headers.
Worked Example
Node.jsA complete example showing how to construct the message, sign it, and send the request. The highlighted lines are the signature-specific portion — wrap them in a helper and reuse across your codebase, or use our SDK.
import { createHmac } from 'node:crypto';
import axios from 'axios';
// Pull sensitive data from environment.
const integration = {
clientId: process.env.INTEGRATION_CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET
};
// Retrieve the current date in UTC ISO-8601 format
// format YYYY-MM-DDTHH:mm:ss (excluding milliseconds and timezone)
const isoDate = new Date().toISOString().split('.')[0]; // i.e. 2025-03-01T02:30:00
// Define request method, URL, and payload.
const request = {
method:'POST',
url: 'https://a-api.coinpayments.net/api/v1/merchant/wallets',
data: {
currencyId: 2,
label: 'Online Shop Wallet',
webhookUrl: 'https://api.my-store.com/webhooks/endpoint',
}, // or null
headers: {
'X-CoinPayments-Client': integration.clientId,
'X-CoinPayments-Timestamp': isoDate,
'X-CoinPayments-Signature': '' // generated below
}
}
// Convert payload to JSON string.
const payloadMessage = request.data ? JSON.stringify(request.data) : '';
// Construct the unique request message.
const message = `\ufeff${request.method}${request.url}${integration.clientId}${isoDate}${payloadMessage}`;
// Hash the message using SHA-256, digesting in Base64.
const signature = createHmac('sha256', integration.clientSecret)
.update(message)
.digest('base64');
// Set request header.
request.headers['X-CoinPayments-Signature'] = signature;
// Send API request.
axios(request)
.then((response) => console.log(response.data))
.catch((err) => console.log(`Error code: ${err.status}`));Where to next?
You've got a signature. Pair it with the other two headers, or rotate your secret if needed.
