◈   ⌘ api · Intermediate

OKX API Passphrase Explained: Setup & Code Examples

Learn how to create and use an OKX API passphrase for secure trading automation. Includes Python and JavaScript code examples with authentication setup.

Uncle Solieditor · voc · 05.05.2026 ·views 22
◈   Contents
  1. → What Is the OKX API Passphrase?
  2. → Creating Your OKX API Key and Passphrase
  3. → Authentication Flow: How the Passphrase Is Used
  4. → Python Code Example: OKX API Authentication
  5. → JavaScript Code Example: Node.js OKX Client
  6. → Common Errors and How to Fix Them
  7. → Security Best Practices for API Credentials
  8. → Frequently Asked Questions
  9. → Conclusion

If you've ever tried connecting a trading bot to OKX and hit a 401 error, the culprit is almost always the passphrase. Unlike Binance or Coinbase, which only require an API key and secret, OKX adds a third layer — a passphrase you set yourself when creating the API key. It's not optional, and it's not recoverable if you lose it. This guide walks through exactly what the passphrase is, how to set it up, and how to include it correctly in your requests.

What Is the OKX API Passphrase?

When you create an API key on OKX, the platform asks you to define three things: an API Key, a Secret Key, and a Passphrase. The passphrase is a custom string you choose — think of it as a second password layered on top of your API credentials. OKX uses it as an additional HMAC signing input and requires it as a header in every authenticated request.

This is different from how Binance handles authentication, where you only need the API key in the header and sign requests with the secret. On OKX, the passphrase travels with every request as the OK-ACCESS-PASSPHRASE header. Forget to include it and you'll get an authentication failure immediately.

Critical: OKX does not store your passphrase anywhere retrievable. If you lose it, you must delete the API key and create a new one. Write it down in a password manager the moment you create it.

Creating Your OKX API Key and Passphrase

Log into your OKX account and navigate to the API management section under your profile settings. Click 'Create API Key' and you'll see fields for a label, passphrase, and permission toggles. The passphrase can be any string you choose — there's no enforced complexity requirement, but treat it like a strong password.

Platforms like Bybit and OKX both offer IP whitelisting for API keys, which is a strong security practice if your bot runs on a fixed server IP. Binance and Gate.io offer similar controls. Enable it whenever possible — it limits blast radius if your credentials are ever leaked.

Authentication Flow: How the Passphrase Is Used

OKX uses HMAC-SHA256 signatures for authenticated endpoints. The signature is built from a concatenation of the timestamp, HTTP method, request path, and request body. Your passphrase does not go into the signature calculation itself — it travels as a plain header. Here's the exact header set required:

Required Headers for OKX Authenticated Requests
HeaderValueNotes
OK-ACCESS-KEYYour API KeyFrom key creation
OK-ACCESS-SIGNHMAC-SHA256 signatureComputed per request
OK-ACCESS-TIMESTAMPISO 8601 UTC timestampe.g. 2024-01-15T10:30:00.000Z
OK-ACCESS-PASSPHRASEYour passphraseSet during key creation
Content-Typeapplication/jsonRequired for POST requests

The timestamp must be within 30 seconds of OKX server time. If your system clock drifts, you'll get timestamp errors that look like authentication failures. Always sync your server clock with NTP before running production bots.

Python Code Example: OKX API Authentication

Here's a complete Python example that builds the authentication headers, makes a signed request to fetch your account balance, and handles common errors:

import hmac
import hashlib
import base64
import time
import requests
from datetime import datetime, timezone

API_KEY = "your-api-key-here"
SECRET_KEY = "your-secret-key-here"
PASSPHRASE = "your-passphrase-here"  # Set during key creation
BASE_URL = "https://www.okx.com"


def get_timestamp():
    """Return ISO 8601 UTC timestamp required by OKX."""
    return datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%S.') + \
           str(datetime.now(timezone.utc).microsecond // 1000).zfill(3) + 'Z'


def sign_request(timestamp, method, path, body=""):
    """Build HMAC-SHA256 signature for OKX request."""
    message = timestamp + method.upper() + path + body
    signature = hmac.new(
        SECRET_KEY.encode('utf-8'),
        message.encode('utf-8'),
        hashlib.sha256
    ).digest()
    return base64.b64encode(signature).decode('utf-8')


def get_headers(method, path, body=""):
    """Build complete auth headers including passphrase."""
    timestamp = get_timestamp()
    return {
        "OK-ACCESS-KEY": API_KEY,
        "OK-ACCESS-SIGN": sign_request(timestamp, method, path, body),
        "OK-ACCESS-TIMESTAMP": timestamp,
        "OK-ACCESS-PASSPHRASE": PASSPHRASE,
        "Content-Type": "application/json"
    }


def get_account_balance():
    """Fetch account balance from OKX."""
    path = "/api/v5/account/balance"
    headers = get_headers("GET", path)

    try:
        response = requests.get(BASE_URL + path, headers=headers, timeout=10)
        response.raise_for_status()
        data = response.json()

        if data.get("code") != "0":
            print(f"OKX API error: {data.get('msg')} (code: {data.get('code')})")
            return None

        return data["data"]

    except requests.exceptions.Timeout:
        print("Request timed out — check your internet connection")
    except requests.exceptions.HTTPError as e:
        print(f"HTTP error: {e.response.status_code} — likely wrong passphrase or expired key")
    except Exception as e:
        print(f"Unexpected error: {e}")

    return None


if __name__ == "__main__":
    balance = get_account_balance()
    if balance:
        for account in balance:
            for detail in account.get("details", []):
                if float(detail.get("availBal", 0)) > 0:
                    print(f"{detail['ccy']}: {detail['availBal']}")

JavaScript Code Example: Node.js OKX Client

For bot developers working in Node.js, here's the equivalent implementation using the built-in crypto module. This example places a limit order and shows how to handle the response:

const crypto = require('crypto');
const https = require('https');

const config = {
  apiKey: 'your-api-key-here',
  secretKey: 'your-secret-key-here',
  passphrase: 'your-passphrase-here',  // Set during key creation
  baseUrl: 'www.okx.com'
};

function getTimestamp() {
  return new Date().toISOString().replace(/\.\d{3}Z$/, '.') +
    String(new Date().getMilliseconds()).padStart(3, '0') + 'Z';
}

function signRequest(timestamp, method, path, body = '') {
  const message = `${timestamp}${method.toUpperCase()}${path}${body}`;
  return crypto
    .createHmac('sha256', config.secretKey)
    .update(message)
    .digest('base64');
}

function buildHeaders(method, path, body = '') {
  const timestamp = getTimestamp();
  return {
    'OK-ACCESS-KEY': config.apiKey,
    'OK-ACCESS-SIGN': signRequest(timestamp, method, path, body),
    'OK-ACCESS-TIMESTAMP': timestamp,
    'OK-ACCESS-PASSPHRASE': config.passphrase,
    'Content-Type': 'application/json'
  };
}

async function placeLimitOrder(instId, side, size, price) {
  const path = '/api/v5/trade/order';
  const body = JSON.stringify({
    instId,           // e.g. 'BTC-USDT'
    tdMode: 'cash',   // 'cash' for spot, 'cross' for margin
    side,             // 'buy' or 'sell'
    ordType: 'limit',
    sz: String(size),
    px: String(price)
  });

  const headers = buildHeaders('POST', path, body);

  return new Promise((resolve, reject) => {
    const options = {
      hostname: config.baseUrl,
      path,
      method: 'POST',
      headers: { ...headers, 'Content-Length': Buffer.byteLength(body) }
    };

    const req = https.request(options, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => {
        const parsed = JSON.parse(data);
        if (parsed.code !== '0') {
          reject(new Error(`OKX error ${parsed.code}: ${parsed.msg}`));
        } else {
          resolve(parsed.data);
        }
      });
    });

    req.on('error', reject);
    req.setTimeout(10000, () => { req.destroy(); reject(new Error('Timeout')); });
    req.write(body);
    req.end();
  });
}

// Example usage
placeLimitOrder('BTC-USDT', 'buy', '0.001', '60000')
  .then(data => console.log('Order placed:', data[0].ordId))
  .catch(err => console.error('Order failed:', err.message));

Common Errors and How to Fix Them

Most OKX API authentication failures come down to a handful of root causes. Knowing them saves you hours of debugging:

Tip: Use OKX's demo trading environment (demo.okx.com) during development. It uses the same API structure but with paper money — you can safely test authentication without risking real funds. Bitget and Bybit offer similar sandbox environments.

If you're building a signal-driven bot, consider pairing your OKX connection with VoiceOfChain — a real-time trading signal platform that pushes alerts via WebSocket and Telegram. Instead of polling the market yourself, you receive structured signals with entry, stop-loss, and take-profit levels that your bot can execute directly through the OKX API.

Security Best Practices for API Credentials

Your API key, secret, and passphrase together grant full trading access to your account. Treat them accordingly:

import os
from dotenv import load_dotenv

# Load from .env file — never hardcode credentials
load_dotenv()

API_KEY = os.getenv('OKX_API_KEY')
SECRET_KEY = os.getenv('OKX_SECRET_KEY')
PASSPHRASE = os.getenv('OKX_PASSPHRASE')

if not all([API_KEY, SECRET_KEY, PASSPHRASE]):
    raise EnvironmentError(
        "Missing OKX credentials. Set OKX_API_KEY, OKX_SECRET_KEY, "
        "and OKX_PASSPHRASE in your .env file."
    )

Frequently Asked Questions

What happens if I forget my OKX API passphrase?
OKX does not store passphrases, so there's no recovery option. You'll need to delete the existing API key and create a new one with a new passphrase. Store it in a password manager immediately after creation to avoid this situation.
Is the passphrase the same as my OKX account password?
No, they are completely separate. Your passphrase is a string you define specifically for a given API key — you can have multiple API keys with different passphrases. Your account login password is never used in API authentication.
Can I use the same passphrase for multiple API keys?
Technically yes, but it's not recommended. Using unique passphrases per key means that if one is compromised you can revoke just that key without worrying about the others. Treat each key as an independent credential set.
Does the OKX passphrase go into the HMAC signature calculation?
No — the HMAC-SHA256 signature is computed from the timestamp, HTTP method, request path, and request body only. The passphrase is sent as a plain header (OK-ACCESS-PASSPHRASE) and is not included in the signature input string.
Why does my OKX signature work in Postman but fail in my code?
The most common cause is body serialization — if your JSON body has different key ordering or whitespace than what you signed, the signature won't match. Serialize the body once, use that exact string for both signing and sending. Also verify your timestamp format matches OKX's ISO 8601 requirement.
Do Binance and Bybit also require a passphrase?
No, neither Binance nor Bybit require a passphrase. Binance uses API key + secret with HMAC signing, Bybit uses a similar two-credential approach. OKX is somewhat unique in requiring this third factor, which is why it catches developers off guard.

Conclusion

The OKX API passphrase is a straightforward concept once you understand its role: it's a static authentication header that travels with every request, separate from the HMAC signature. The most common mistakes are losing it (unrecoverable), miscasing it, or missing it entirely from request headers. With the Python and JavaScript examples above, you have working authentication code you can adapt for your own trading bots — whether you're building a simple balance checker, an order execution engine, or a full automated strategy that feeds off real-time signals from VoiceOfChain. Store your credentials securely, use IP whitelisting, and keep your keys scoped to the minimum permissions your bot actually needs.

◈   more on this topic
◉ basics Mastering the ccxt library documentation for crypto traders ⌂ exchanges Mastering the Binance CCXT Library for Crypto Traders ⌬ bots Best Crypto Trading Bots 2025: Profitable AI-Powered Strategies