Integrating secure and reliable API authentication is a foundational step when building on Web3 infrastructure. This guide walks you through the essential requirements for authenticating REST API requests within the Wallet-as-a-Service (WaaS) ecosystem, ensuring your applications communicate securely with backend services.
Whether you're retrieving wallet balances, initiating transactions, or managing user identities, understanding how to properly sign and structure your requests is crucial. Below, we break down the core components of REST API authentication, including header requirements, signature generation, and practical implementation examples.
Required Request Headers
All private REST API requests must include specific headers to authenticate the caller and validate request integrity. These headers ensure that only authorized applications can access protected endpoints.
The following headers are mandatory:
OK-ACCESS-KEY
Your API key, generated via the developer portal. This unique identifier links the request to your application. Generate your API key here.OK-ACCESS-SIGN
A Base64-encoded HMAC SHA256 signature derived from request metadata and your secret key. This proves the authenticity of the request.OK-ACCESS-TIMESTAMP
The UTC timestamp of the request in ISO format (e.g.,2020-12-08T09:08:57.715Z). The system allows a 30-second time window to prevent replay attacks.OK-ACCESS-PASSPHRASE
The passphrase you set when creating the API key. It adds an additional layer of security beyond the key itself.
For certain services like Wallet-as-a-Service (WaaS), an extra header is required:
OK-ACCESS-PROJECT
The unique project ID associated with your application. You can find this in your project settings dashboard.
👉 Learn how to securely manage your API credentials and start integrating today.
All requests must also use application/json as the content type and contain valid JSON in the body where applicable.
How to Generate the Signature
The OK-ACCESS-SIGN header is critical for request validation. It ensures that each request is cryptographically signed using your private secret key, preventing tampering and unauthorized use.
Signature Formula
sign = Base64(HMAC_SHA256(secretKey, timestamp + method + requestPath + body))Where:
timestamp: Matches theOK-ACCESS-TIMESTAMPheader (ISO format).method: HTTP method in uppercase (e.g.,GET,POST).requestPath: API endpoint path (e.g.,/api/v5/account/balance).body: Request body string (if present); omitted forGETrequests.- Note: Query parameters in
GETrequests are part of therequestPath, not the body.
- Note: Query parameters in
Step-by-Step Process
- Retrieve your Secret Key from the developer portal.
Construct the pre-hash string by concatenating:
- Timestamp
- Uppercase HTTP method
- Full request path (including query parameters)
- Request body (if any)
- Use HMAC SHA256 to hash the string with your secret key.
- Encode the resulting hash using Base64.
Example in JavaScript
const CryptoJS = require("crypto-js");
const timestamp = "2020-12-08T09:08:57.715Z";
const method = "GET";
const requestPath = "/api/v5/account/balance?ccy=BTC";
const body = "";
const secretKey = "your-secret-key";
const message = timestamp + method + requestPath + body;
const sign = CryptoJS.enc.Base64.stringify(
CryptoJS.HmacSHA256(message, secretKey)
);This generated sign value should be assigned to the OK-ACCESS-SIGN header.
Using Postman for API Testing
Postman is a powerful tool for testing and debugging API integrations. It allows developers to send HTTP requests, inspect responses, and automate workflows—all within a user-friendly interface.
While no longer required for production use, Postman remains ideal for development and troubleshooting.
Adding Query Parameters
For GET requests, add query parameters under the Params tab. Enter key-value pairs such as ccy: BTC, which will be appended to the URL automatically.
Setting Headers
Navigate to the Headers tab and include:
OK-ACCESS-KEYOK-ACCESS-PASSPHRASEOK-ACCESS-PROJECT(if applicable)Content-Type: application/json
Leave OK-ACCESS-SIGN and OK-ACCESS-TIMESTAMP for dynamic generation.
Configuring Request Body
For POST, PUT, or PATCH requests:
- Go to the Body tab.
- Select raw and choose JSON from the dropdown.
Enter your payload in valid JSON format, e.g.:
{ "instId": "BTC-USDT", "lever": "5", "mgnMode": "isolated" }
Pre-request Script Setup
Use the Pre-request Script tab to dynamically generate headers before sending the request.
For GET Requests:
const timestamp = new Date().toISOString();
pm.environment.set("timestamp", timestamp);
const method = request.method;
const path = request.url.getPath();
const params = request.url.getQueryString();
const fullUrl = params ? `${path}?${params}` : path;
const secret = pm.environment.get("secretKey");
const message = timestamp + method + fullUrl;
const signature = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(message, secret));
pm.request.headers.add({
key: 'OK-ACCESS-SIGN',
value: signature
});
pm.request.headers.add({
key: 'OK-ACCESS-TIMESTAMP',
value: timestamp
});For POST Requests:
Include the JSON body in the message string:
const body = request.data ? JSON.stringify(request.data) : "";
const message = timestamp + method + fullUrl + body;👉 Streamline your testing workflow with secure, automated request signing.
JavaScript Integration Example
Here’s a complete example of making an authenticated API call using Node.js:
const axios = require('axios');
const CryptoJS = require('crypto-js');
async function makeAuthenticatedRequest() {
const baseURL = 'https://web3.okx.com';
const endpoint = '/api/v5/account/balance';
const method = 'GET';
const url = baseURL + endpoint;
const apiKey = 'your-api-key';
const secretKey = 'your-secret-key';
const passphrase = 'your-passphrase';
const timestamp = new Date().toISOString();
// Generate signature
const message = timestamp + method + endpoint;
const sign = CryptoJS.enc.Base64.stringify(
CryptoJS.HmacSHA256(message, secretKey)
);
try {
const response = await axios.get(url, {
headers: {
'OK-ACCESS-KEY': apiKey,
'OK-ACCESS-SIGN': sign,
'OK-ACCESS-TIMESTAMP': timestamp,
'OK-ACCESS-PASSPHRASE': passphrase,
'Content-Type': 'application/json'
}
});
console.log(response.data);
} catch (error) {
console.error('Request failed:', error.response?.data || error.message);
}
}
makeAuthenticatedRequest();This pattern can be reused across different endpoints by adjusting the method, path, and body accordingly.
Frequently Asked Questions
Q: What happens if my timestamp is out of sync?
A: Requests with timestamps more than 30 seconds apart from server time will be rejected. Always use UTC and synchronize your system clock.
Q: Can I reuse the same API key across multiple projects?
A: No. Each project requires its own set of credentials for security and tracking purposes. Use separate keys per environment (dev, staging, prod).
Q: Is it safe to expose my API key in client-side code?
A: Never expose your secret key or API key in frontend or public repositories. Always handle authentication on secure backend servers.
Q: How do I revoke a compromised API key?
A: Immediately log into your developer dashboard and delete or disable the affected key. Then generate a new one.
Q: Why am I getting an invalid signature error?
A: Double-check that you're using the correct secret key, exact timestamp, proper HTTP method, and full request path—including query strings.
Q: Do I need to URL-encode query parameters when signing?
A: Yes. Ensure all query parameters are properly encoded as they appear in the final URL used in the signature string.
Final Recommendations
Secure API integration starts with correct authentication practices. Always store credentials securely using environment variables or secret managers. Avoid hardcoding keys in source files.
Monitor your API usage regularly and enable logging to detect anomalies early.
👉 Get started with robust, secure Web3 API access—integrate with confidence.
By following this guide, you'll ensure your application meets industry standards for security, reliability, and performance when interacting with Web3 services.