Solving Common OKX API Authentication Issues: Timestamp Expired and Invalid Sign

·

Integrating with cryptocurrency exchange APIs like OKX can be a powerful way to automate trading strategies, monitor portfolios, or build custom analytics tools. However, developers often encounter frustrating authentication errors—particularly "timestamp request expired" and "invalid sign"—when making signed API requests. These issues can halt progress, especially when the root causes aren't immediately obvious.

This guide dives deep into diagnosing and resolving these two common OKX API authentication problems. Whether you're building a quantitative trading bot or simply fetching account data, understanding how to correctly format timestamps and generate valid signatures is essential for seamless integration.

Understanding the "Timestamp Request Expired" Error

One of the first hurdles developers face is the timestamp request expired error. At first glance, it seems straightforward: your system time doesn’t match the exchange server’s time. But even if your clock is synchronized using UTC, you might still run into this issue.

The real culprit? Incorrect timestamp formatting.

OKX requires timestamps in ISO 8601 format with millisecond precision and a trailing "Z" (e.g., 2025-04-01T14:13:28.849Z). Many developers use Python’s datetime.utcnow().isoformat() method, which produces a string like 2025-04-01T14:13:28.849000. Notice the extra microsecond digits and missing "Z".

👉 Discover how to generate perfectly formatted timestamps for secure API access.

Here’s the corrected function to generate a valid timestamp:

import datetime as dt

def get_time():
    return dt.datetime.utcnow().isoformat()[:-3] + 'Z'

This trims off the extra microsecond precision and appends the required "Z" to indicate UTC time. Using this formatted timestamp ensures your request falls within OKX’s acceptable time window—typically within 30 seconds of the server time.

Fixing the "Invalid Sign" Error in API Requests

Even with the correct timestamp, you may still receive an invalid sign error. This occurs when the HMAC-SHA256 signature doesn't match what OKX expects. The signing process involves concatenating several components:

However, a subtle but critical detail lies in the order of inputs during HMAC generation.

While documentation might suggest that the message should be signed as (message + secret_key), some cryptographic libraries—including Python’s hmac module—behave differently. In practice, the secret key must be passed as the key parameter, not concatenated manually.

Here’s the proper implementation:

import base64
import datetime as dt
import hmac
import requests
import os

APIKEY = os.getenv('KEY')
APISECRET = os.getenv('SECRET')
PASS = os.getenv('PASSPHRASE')
BASE_URL = 'https://www.okx.com'

def signature(timestamp, method, request_path, body, secret_key):
    if str(body) == '{}' or str(body) == 'None':
        body = ''
    message = str(timestamp) + str.upper(method) + request_path + str(body)
    mac = hmac.new(
        bytes(secret_key, encoding='utf8'),
        bytes(message, encoding='utf-8'),
        digestmod='sha256'
    )
    d = mac.digest()
    return base64.b64encode(d).decode('utf-8')

Note that we decode the final signature back to a string using .decode('utf-8') so it can be properly included in headers.

Building a Complete Signed Request Function

With both timestamp and signature logic fixed, let’s assemble a robust function to send authenticated requests:

def send_signed_request(http_method, url_path, payload={}):
    cur_time = get_time()
    header = {
        'Content-Type': 'application/json',
        'OK-ACCESS-KEY': APIKEY,
        'OK-ACCESS-SIGN': signature(cur_time, http_method, url_path, payload, APISECRET),
        'OK-ACCESS-TIMESTAMP': cur_time,
        'OK-ACCESS-PASSPHRASE': PASS
    }
    url = BASE_URL + url_path
    response = requests.request(http_method, url, headers=header, json=payload)
    return response.json()

You can now safely call:

send_signed_request("GET", "/api/v5/account/balance")

This will return your account balance without triggering authentication errors—provided your environment variables (KEY, SECRET, PASSPHRASE) are correctly set.

👉 Learn how to automate trading strategies securely with reliable API integrations.

Core Keywords for Search Visibility

To ensure this content reaches developers searching for solutions, here are the core keywords naturally integrated throughout:

These terms align with common search queries from developers troubleshooting OKX connectivity issues.

Frequently Asked Questions

Why do I get "timestamp request expired" even with correct UTC time?

Even if your system uses UTC, OKX enforces strict formatting and synchronization. Ensure your timestamp includes milliseconds, is trimmed to three decimal places, and ends with "Z". Also verify your system clock is synchronized via NTP.

Does the request body always need to be empty if no parameters are sent?

Yes. When there's no payload, the body should be treated as an empty string ('') rather than {} or None in the signature message. This prevents mismatched hashing.

Can I reuse this code for other HTTP methods like POST or PUT?

Absolutely. The send_signed_request function supports all HTTP methods. Just ensure that for POST requests, you pass the payload correctly and include it in the signature generation.

Is it safe to store API keys in environment variables?

Yes, using environment variables (os.getenv) is considered a best practice for managing secrets locally. For production systems, consider using secure secret management services like Hashicorp Vault or AWS Secrets Manager.

What permissions do I need on my OKX API key?

For balance queries, ensure your API key has "Read" permission enabled under the "Account" section. Avoid granting unnecessary write or trade permissions unless required.

How can I test my API connection before going live?

Use sandbox endpoints during development. OKX provides a testnet environment where you can simulate requests without affecting real funds or triggering rate limits on the mainnet.


By addressing both timestamp formatting and HMAC signing order, you can overcome the most common barriers to successful OKX API integration. With clean, well-documented code and attention to detail, automated trading and portfolio monitoring become far more achievable.

👉 Start building your own trading automation with confidence today.