Understanding OKX API Authentication
When working with OKX's REST API for private endpoints, proper authentication is crucial. All requests must include specific headers and follow a precise signing process to avoid the common "Invalid Sign" error (Code 50113).
Required Request Headers
Every private API call to OKX must contain these headers:
OK-ACCESS-KEY: Your API key (string)OK-ACCESS-SIGN: Base64-encoded HMAC SHA256 signatureOK-ACCESS-TIMESTAMP: UTC timestamp in ISO format (e.g.,2020-12-08T09:08:57.715Z)OK-ACCESS-PASSPHRASE: The passphrase you set during API key creation
For simulated trading, add:
x-simulated-trading: 1
๐ Learn more about API authentication best practices
The Signature Generation Process
Creating a valid signature involves these steps:
Concatenate these components:
- Timestamp (same as
OK-ACCESS-TIMESTAMP) - HTTP method in uppercase (GET/POST/PUT/DELETE)
- Request path (e.g.,
/api/v5/account/balance) - Request body (for POST/PUT requests)
- Timestamp (same as
- Create HMAC SHA256 hash using your Secret Key
- Base64-encode the resulting hash
Signature Formula
sign = Base64.encode(HMAC_SHA256(timestamp + method + requestPath + body, secretKey))Common Pitfalls and Solutions
Many developers encounter the "Invalid Signature" error due to:
Timestamp format issues
- Must use ISO 8601 format with milliseconds
- Example:
2023-03-15T08:12:45.123Z
Method case sensitivity
- Always use uppercase (GET, not get)
Path inconsistencies
- Include full path with query parameters for GET requests
- Example:
/api/v5/account/balance?ccy=BTC
Body handling mistakes
- For GET requests with no body: omit it
- For POST: include raw JSON string (unformatted)
Secret key errors
- Using wrong key (check API dashboard)
- Extra spaces in key string
Working Code Example
Here's how to properly structure a balance check request:
import hashlib
import hmac
import base64
import time
import requests
api_key = "YOUR_API_KEY"
secret_key = "YOUR_SECRET_KEY"
passphrase = "YOUR_PASSPHRASE"
timestamp = time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime())
method = "GET"
request_path = "/api/v5/account/balance"
# Create signature
message = timestamp + method + request_path
signature = base64.b64encode(
hmac.new(
secret_key.encode("utf-8"),
message.encode("utf-8"),
hashlib.sha256
).digest()
).decode("utf-8")
headers = {
"OK-ACCESS-KEY": api_key,
"OK-ACCESS-SIGN": signature,
"OK-ACCESS-TIMESTAMP": timestamp,
"OK-ACCESS-PASSPHRASE": passphrase,
"x-simulated-trading": "1" # For sandbox
}
response = requests.get(
"https://www.okx.com" + request_path,
headers=headers
)๐ Explore OKX API documentation for advanced implementations
FAQ: Solving Signature Problems
Why does my API call return "Invalid Sign"?
This typically indicates:
- Incorrect timestamp format
- Wrong signature calculation
- Mismatched secret key
- Improper method casing
How do I verify my signature is correct?
- Compare against OKX's example signatures
- Use online HMAC SHA256 generators to validate
- Check timestamp precision (milliseconds matter)
Should GET request parameters be in the path or body?
All GET parameters belong in the request path:
/api/v5/account/balance?ccy=BTCWhy does my sandbox request fail?
Ensure you:
- Added
x-simulated-trading: 1header - Are using sandbox API endpoints
- Created sandbox-specific API keys
How often should I rotate my API keys?
For security:
- Rotate keys every 3-6 months
- Immediately revoke compromised keys
- Use IP whitelisting where possible
Best Practices for API Security
Key management
- Never expose secret keys in client-side code
- Store keys in secure environment variables
Request validation
- Verify response signatures
- Implement request rate limiting
Error handling
- Gracefully handle 50113 errors
- Implement automatic retry with backoff
By following these guidelines and ensuring proper signature generation, you'll avoid common authentication issues and build reliable integrations with OKX's trading API.