MeowQuant is an independent third-party information site, not OKX official. This site contains affiliate links, and we may earn a fee from them. Full disclosure →

OKX · API Hands-On

OKX API Quant Starter: Create a Demo Key, Place and Cancel Your First Order

You probably got here like this: you saw a few profit screenshots from quant influencers, got tempted, opened your OKX dashboard ready to start—and hit a wall at step one. You click into "API Management" and there's a pile of options: apiKey, Secret, Passphrase, Read, Trade, Withdraw, IP whitelist. You recognize every word, but strung together you have no idea what to fill in. So you close the tab and tell yourself "maybe later."

This piece is here to get you past that wall. Below, the whole journey—from zero to a working first order script in Python—is broken into a few steps, with the easy-to-miss spots flagged along the way. By the end you should be able to create a least-privilege API Key inside OKX's demo trading environment, confirm it works with a dozen lines of code, then place and cancel your first order on the demo account and check that the status it returns matches what you expect. You don't need to be a programmer—just follow along and copy.

First, ask yourself: do you actually need the API?

This is the question to settle before you start. Opening an API and writing scripts has a cost—you have to set up the environment, debug the code, and guard against your own fat-finger mistakes. If your needs are actually simple, there's a good chance you never have to touch the API at all.

OKX's built-in "Trading Bots" section has ready-made grid bots, DCA, and futures arbitrage tools. You set the parameters with a few clicks on the web or app, and it runs for you—no code required. If you are just starting out and only want a program to handle your buy and sell orders, the built-in bots are plenty, and when something goes wrong you have an interface to watch and stop it directly.

So when is the API worth it? Here's how we'd call it—roughly these situations:

  • You want strategy logic the built-in bots can't do, like dynamically rebalancing based on some indicator, or coordinating across multiple coins.
  • You want to backtest, which means pulling historical candles in bulk and simulating fills. (Note: historical candles are public market data — you can pull them without creating a Key at all. Backtesting itself needs no API Key, let alone withdrawal permission.)
  • You want to run several strategies at once and manage them all through a script instead of by hand.
  • You simply want to learn quant trading, using the exchange as a sandbox to practice in.

If any of those is you, read on. But if you realize you just want to "set up a grid and let it earn off the chop while I sleep," you might as well open a built-in grid in the dashboard first; once you actually hit the ceiling of the built-in tools, it's not too late to come back and open the API. We have a whole separate piece on how to set grid bot parameters, which suits you if you take that road.

Three things to understand before you create a Key

Before you actually create a Key, there are three things you need to get straight. Click "Create" without understanding them and you'll most likely either fail to connect or quietly bury a security hole for yourself.

① You'll get three credentials, not two

If you assume an API is just "one account, one password," on OKX you may do a double-take—it hands you three things:

  • apiKey: the public identifier for this Key, like a "username."
  • secret (Secret Key): the key used to sign requests, like a "password"—shown only once, at creation.
  • Passphrase: a string you set yourself at creation, unique to OKX.

That third one, the Passphrase, is where beginners easily trip up. It's not your OKX login password—it's a separate string you set up when creating this particular Key. What makes it worse: in Python's ccxt library, this field isn't called passphrase, it's called password. So it's easy to take it at face value and enter your login password, then scratch your head at the "authentication failed" error. Remember one line and you're fine: the password in ccxt = the Passphrase you set when creating the Key.

② Tick only "Trade"—never "Withdraw"

When you create the Key, OKX asks what this Key is allowed to do. There are three main levels:

  • Read: balances, orders, bills — the look-but-don't-touch endpoints. Lowest risk. (Worth noting in passing: candles, order book and ticker are public market data and need no API Key at all, so if you're only pulling data to backtest, you don't have to create a Key in the first place.)
  • Trade: place, cancel, and amend orders. Required to run a strategy. And here's the part that's easy to miss — by OKX's own definition, the trade permission also covers funding transfers (funding account ↔ trading account, main account ↔ sub-accounts) and part of the account settings. It is not just "buy and sell."
  • Withdraw: move coins out to an on-chain address.

Here's a security line with almost no exceptions: for a quant Key, tick only "Read" and "Trade"—never tick "Withdraw." The logic is direct: tick withdrawal and a leak is like handing over the keys to your safe; leave it off and at least nobody can move your coins out to an on-chain address. Do not mistake that for insurance, though, and note that what it holds back is narrower than you'd think — as said above, the trade permission itself covers funding transfers and part of the account settings, so the holder can still shuffle money between your funding account, trading account and sub-accounts. On top of that, a trade-only key can still wipe you out: whoever holds it can push orders through on a thin, illiquid pair and take the other side themselves; your principal leaves as "trading losses", every line of it reads like an ordinary fill, and it is far harder to chase afterwards than a suspicious withdrawal. What actually works is all three together: no withdrawal permission, an IP allowlist, and rotating the key. Automated trading never needs to withdraw anything, so this permission gives you only downside, no upside.

Bottom line: there are people scanning public repositories for exactly this kind of string, and a leaked Key with withdrawal ticked leaves you almost no time to react — one request moves the assets to an address of their choosing, and an on-chain transfer cannot be reversed. Withdrawal permission is zero-necessary for a quant script; ticking it is asking for trouble.

③ Whether to set an IP whitelist

OKX lets you bind an IP whitelist to a Key—only requests from the specified IPs are accepted. It's a well-worth-it extra layer of insurance.

The decision is simple. If your script runs on a machine with a fixed IP (a cloud server, or home broadband with a static public IP), add that IP to the whitelist and your security goes up a notch immediately. OKX lets each Key bind up to 20 IPs, CIDR ranges included, so "my egress changes now and then" doesn't automatically mean giving up on a whitelist.

If your home broadband IP keeps moving and you can't bind one yet, two things to know first. One: a Key with no IP bound can be called from any machine at all, so the credentials are the only door. Two: by the official rules, a Key with no IP bound that carries trade or withdraw permission is automatically deleted after 14 days of inactivity. So it isn't "bound or not, same thing" — it's "not bound yet means guarding the credentials that much harder." While you're practising, the easier route is a demo Key: it trades play money, and it isn't subject to that deletion rule either. Once you move the script onto a fixed-IP machine for the long haul, adding the whitelist is the first thing to do.

Creating the API Key in the OKX dashboard

With those three things understood, go create the Key. First, let's be clear about which one this article wants you to create: a demo (Demo Trading) Key. OKX's demo and live are two independent environments, and the Key has to be created separately inside the demo trading environment — no toggle turns a live Key into a demo one. The order and cancel scripts later in this article really do submit orders to the exchange, so use the demo Key for your first run; once the flow is smooth, create a live one by the same steps.

Here's the path for creating a Key, per the current OKX dashboard (the UI gets tweaked occasionally, but the logic stays the same; if you want a demo Key, switch into the demo trading environment first, then walk through this flow):

  1. Log in to OKX, hover over your avatar in the top right, find "API" or "API Management" in the dropdown, and click in.
  2. On the API management page, click "Create API Key." If it asks about the purpose, choose the personal-trading type—don't choose third-party access.
  3. Give the Key a name (note), like meow-grid-bot, so you can tell at a glance what it's for later.
  4. Set the Passphrase. Here you define a string yourself—commit it to memory, because ccxt will need it later, it's bound to this Key only, and if you lose it you can only delete and recreate.
  5. Tick the permissions: tick "Read" and "Trade," do not tick "Withdraw." (Per the previous section's bottom line.)
  6. If you run on a fixed-IP machine, fill in the IP whitelist (up to 20 IPs per Key, CIDR ranges supported). Leaving it blank works too, but know the price: by the official rules, a Key with no IP bound that carries trade or withdraw permission is automatically deleted after 14 days of inactivity, and it can be called from any machine at all.
  7. Click confirm and pass two-factor verification (phone / email / authenticator app).
  8. The page will show the apiKey and Secret Key. The Secret is shown only this once—copy and save it somewhere safe right away. Close the page and you'll never see it again; lose it and you can only delete the Key and recreate.

At this point you should have three things in hand: the apiKey, the Secret, and the Passphrase you set yourself. Store them in a local file that won't be synced or uploaded—don't screenshot and send it over chat, don't paste it into any online notes app. Next we'll use these three credentials to connect.

Connecting with Python + ccxt and confirming it works

Credentials in hand, the next step is verifying they actually work. We use ccxt—a library that wraps hundreds of exchanges' APIs behind a single unified interface, so you don't have to wade through OKX's raw signing details and can check balances and place orders in a few lines.

Install it first. Open a terminal (command line) and type:

pip install ccxt

Once installed, create a file okx_check.py, copy in the block below, and replace the three placeholders in quotes with your own credentials:

import ccxt

# Three credentials: apiKey, secret, password (= Passphrase)
okx = ccxt.okx({
    'apiKey':   'YOUR_DEMO_apiKey',
    'secret':   'YOUR_DEMO_secret',
    'password': 'YOUR_DEMO_Passphrase',   # OKX-specific, easy for beginners to miss
})

# The key line: a demo Key needs the demo header on every request
okx.set_sandbox_mode(True)

# Self-check: 1 means you're on demo
print(okx.headers.get('x-simulated-trading'))

# Pull the account balance to confirm auth works
balance = okx.fetch_balance()
print('USDT free:', balance['USDT']['free'])
print('USDT total:', balance['USDT']['total'])

Save it and run python okx_check.py in the terminal. The credentials here are the demo Key from the previous section, so the sandbox switch has to be on; leave out that set_sandbox_mode(True) line and OKX answers with 50101 (APIKey does not match current environment). If it prints the virtual USDT balance in your demo account, congratulations—auth works and the API is connected. If it errors, don't panic—the usual culprit is one of the three credentials being wrong or missing. Jump to the "gotchas beginners easily hit" section of this article and cross-check; it lists the cause behind each error.

One more word on storing credentials: above, to keep things clear, we wrote the credentials straight into the code, but that's only fine for a one-off local test. Once a script is going to run long-term, let alone on a server, don't hard-code the credentials—switch to environment variables or a separate config file, and make sure that file isn't synced or committed to a code repo. This is the key habit that keeps the odds of your account being stolen as low as possible.

Your first order script: placing and cancelling

Being able to check the balance means your read permission works; now test the trade permission—place an order, then cancel it. Here we use a limit order rather than a market order, because with a limit order you set the price yourself: set it far from the market price and it won't fill right away, which lets you practice placing and cancelling without actually spending money.

Before placing an order, two small things to understand:

How to write the symbol (trading pair). In ccxt, spot pairs are written uniformly as base/quote, so Bitcoin against USDT is BTC/USDT and Ethereum against USDT is ETH/USDT. Note it's a forward slash, uppercase. Getting the format wrong is another common source of errors.

Order parameters. ccxt's order method is create_order(symbol, type, side, amount, price), with the five arguments being: trading pair, order type (limit / market), side (buy / sell), amount, and price.

The block below places a deliberately-won't-fill low-price limit buy, then cancels it the moment it has the order ID. This one genuinely submits an order to the exchange, so the credentials below are written as demo-account ones from the start—how you create a demo Key, and what the sandbox toggle actually does, is unpacked in the next section:

import ccxt, time

# 🔴 This block really does place an order, so the credentials must be your
#    demo (Demo Trading) Key. That Key is created separately inside the demo
#    trading environment; the live one is not the same set of credentials.
okx = ccxt.okx({
    'apiKey':   'YOUR_DEMO_apiKey',
    'secret':   'YOUR_DEMO_secret',
    'password': 'YOUR_DEMO_Passphrase',
})

# The key line: without it, the order below is real money resting on the live book
okx.set_sandbox_mode(True)

# Self-check: this must print 1. If it prints None, stop before going further
print(okx.headers.get('x-simulated-trading'))

symbol = 'BTC/USDT'

# A limit buy designed not to fill: price far below market
order = okx.create_order(
    symbol=symbol,
    type='limit',
    side='buy',
    amount=0.0001,     # tiny amount, go by the minimum order size
    price=20000,       # far below current BTC price, sits unfilled
)
order_id = order['id']
print('Order placed, id:', order_id)

time.sleep(2)

# Cancel the order we just placed
canceled = okx.cancel_order(order_id, symbol)
print('Cancellation request accepted:', canceled['id'])

# The cancel response carries no status field — it only means the request was taken
time.sleep(1)
od = okx.fetch_order(order_id, symbol)
print(od['status'])  # cancelling is only an acknowledgement; this is the real final state

Once it runs you'll see three lines of output: first the order ID, two seconds later the acknowledgement of the cancel request, and a second after that the order's actual state. Don't skip that last step: the cancel response carries no status field, so whether it really cancelled has to be checked separately — what OKX's cancel endpoint returns is just "request received," and whether the order ended up canceled or had already filled before you cancelled is something only a follow-up fetch_order will show you. With those three lines your script can do a full "place — cancel — verify," which is the basic set of moves in quant trading. Everything else—grids, DCA, hedging—is essentially these moves with some decision logic and loops bolted on.

On amount: every trading pair has a minimum order size and a precision limit, and too small a value gets rejected by the exchange. If you get a "size doesn't meet rules" error, use okx.load_markets() to check this pair's limits and precision, and fill in the minimum it requires.

Demo first: run it with play money

For all the code above, we strongly recommend you run it on the demo account first, confirm everything works, then switch to real money. The demo uses virtual funds, so wrong orders and buggy logic won't actually lose you money—this is the cheapest step in your beginner phase, with almost no reason to skip it.

OKX's demo is called Demo Trading, and you can switch into it on both the app and the web. One thing to watch: the demo uses its own API Key—the path OKX documents is to create a separate Demo Trading API Key inside the demo trading environment, rather than adding a toggle to your live Key. Once the credentials are swapped, to make ccxt send requests to the demo instead of live, just flip the sandbox toggle after initialization:

import ccxt

# Note: these three are your demo (Demo Trading) Key, not the live one
okx = ccxt.okx({
    'apiKey':   'YOUR_DEMO_apiKey',
    'secret':   'YOUR_DEMO_secret',
    'password': 'YOUR_DEMO_Passphrase',
})

# The key line: make ccxt attach the demo header to every later request
okx.set_sandbox_mode(True)

# Self-check: this line must print 1, otherwise you are still on live
print(okx.headers.get('x-simulated-trading'))

# After this, all requests carry the demo flag and use virtual funds
balance = okx.fetch_balance()
print('Demo USDT free:', balance['USDT']['free'])

Don't substitute the config's sandboxMode for that line: the demo header is added by the set_sandbox_mode() method itself, so writing it into the constructor's options never triggers it and the request still lands on live. Once that print comes back 1, you can run that place–cancel script over and over without worry: even if you fat-finger the price near the market and it actually fills, what you spend is virtual USDT.

A habit worth building: any new strategy, any changed code, gets run on the demo continuously for a while first, confirming order callbacks, cancellations, and balance changes all match expectations, before you remove that set_sandbox_mode(True) line, swap the credentials back to your live Key, and switch to live—and the first live run uses only a tiny amount. This order can save you several times: many logic bugs surface during the demo stage, and had you gone straight to real money the cost would have been more than just cash.

📋 Demo order example
Use the ccxt script above on OKX Demo Trading to place a BTC/USDT limit buy: amount 0.0001, price hard-coded clearly below the current market (the code uses 20000, so it sits unfilled). The object create_order returns carries the order ID — pull it out and keep it; after sleep(2), cancel_order cancels it — what the cancel request returns is only an acknowledgement; query fetch_order once more and only then does status read canceled. To verify the fill path as well, move the price above market so it fills, then use fetch_balance to see whether the demo BTC balance rises accordingly and whether the callback fields line up. Walk that "place → cancel → re-check state" chain end to end and the logic checks out. This step uses nothing but play money, but once the flow runs smoothly you feel a lot steadier when the real money goes in.

Gotchas beginners easily hit

This is the section of this article most worth bookmarking. Each item below lists what the error looks like and where to look, so when something breaks you can check against it.

Passphrase missing / wrong

The error is usually an auth one (something like "Invalid sign" or "passphrase incorrect"). Check that the password field in ccxt holds the Passphrase you set when creating the Key—not your login password, and not the secret. Don't guess from impressions, though: dig the code out of the error first. 50105 is the one that means "wrong Passphrase"; 50113 means the signature itself didn't pass, and the two send you looking at different things.

Demo Key and live mixed up (50101)

A 50101 means the Key itself is fine but it doesn't match the environment (demo vs. live): check whether set_sandbox_mode is on, and whether the Key in your hand belongs to that same environment.

Timestamp error / request expired

OKX has a tolerance for request timestamps; if your computer's or server's system time is off (more than 30 seconds away from server time), the request gets rejected as an expired timestamp (error 50102). The fix is to sync your system time to accurate network time (turn on NTP auto-sync). Cloud servers usually have it on by default; local machines occasionally drift.

Permission denied

If you can check the balance but not place orders, it's basically that you only ticked "Read" and not "Trade" when creating the Key. Go back to API management and add the Trade permission to this Key—no need to recreate.

Hitting the rate limit

If you hammer price queries or place/cancel orders in a loop, you'll hit the endpoint rate limit and get something like "Too Many Requests." The easiest fix is to turn on ccxt's rate limiter at init: ccxt.okx({..., 'enableRateLimit': True}), which automatically inserts gaps between requests. Don't use a while True with no delay to hammer the endpoint.

Wrong symbol

Writing BTC/USDT as BTCUSDT, btc/usdt, or using a futures format for a spot order all throw "instrument does not exist." Remember spot is UPPER/UPPER with a slash; if unsure, run print(okx.load_markets().keys()) first to see what the available pairs actually look like.

IP not on the whitelist

If you set a whitelist, changing networks (turning on a proxy, or your broadband IP changing) gets you rejected. Confirm your current outbound IP is still on that Key's whitelist; if not, go update the list in the dashboard.

Risk and mindset: quant doesn't mean guaranteed profit

Now that you can run a script, we owe you a splash of cold water. Handing trading to a program won't make you money automatically—it only executes your decisions faster and with less emotion. If your strategy itself loses money, automating it just makes you lose faster and more consistently.

And API automation has its own particular risk: a program never hesitates like a human. A miswritten loop, a flipped buy/sell direction, an amount missing a decimal point—things you might catch before hitting confirm by hand—a script will faithfully and continuously execute dozens of times. Say one condition in a loop is written backwards: it can fire off a string of orders that should never have been placed within seconds. On live, that would be real money.

So a few practical pieces of advice for when you're just starting out:

  • Start small. For your first live run, use an amount you wouldn't mind losing entirely. Treat it as tuition, not capital.
  • Set position caps. Hard-code limits on single-order and total position size in the script, so the program never gets a chance to bet all your funds.
  • Keep a stop-loss. However good the strategy looks, give it an explicit stop-loss or maximum-drawdown line that halts on trigger.
  • Be cautious with futures and leverage. This whole article is about spot. Leveraged futures can zero out your capital in a very short time, so at the beginner stage we strongly suggest sticking to spot until your flow and mindset are steady.
  • Watch it run for a while. In the first few days of a new strategy going live, don't actually walk away—watch it, and confirm its behavior matches what you saw on the demo.
Risk note: crypto asset prices swing violently, and your capital can shrink sharply or even go to zero. API automation amplifies execution speed, so once a strategy or its code is flawed, losses get amplified in step; futures and leveraged trading can lead to 100% loss of capital. This article is a summary of the official docs and how the API is used, and is not investment advice of any kind. Use only spare money you can afford to lose entirely, and take responsibility for your own account security and trading decisions.

FAQ

If I enable the API, is my money safe?

Leave the Withdraw permission unticked and nobody who gets hold of your apiKey, secret and Passphrase can move your coins out to an on-chain address. Do not read that as insurance, though, and note that what it holds back is narrower than you might assume: per OKX's documentation, the trade permission itself covers funding transfers and part of the account settings, so the holder can still shuffle money between your funding account, trading account and sub-accounts; on top of that, a trade-only key can still wipe you out—whoever holds it can push orders through on a thin, illiquid pair and take the other side themselves, so your principal leaves as trading losses while every line reads like an ordinary fill. Use all three together: no withdrawal permission, an IP allowlist, and rotating the key. The real danger is storing the three credentials in plain text somewhere that gets uploaded, or enabling withdrawal.

Can I use the API if I can't code?

Writing your own scripts means knowing a little Python, but you can run quant strategies without code—OKX has built-in grid and DCA bots you can use without touching a single line. The API suits people who want custom logic, backtesting, or to run several strategies at once. Figure out which camp you're in before you decide to open an API.

Does the demo-account API Key work for live trading too?

They are not interchangeable. The path OKX documents is to create a separate Demo Trading API Key inside the demo trading environment, rather than adding a toggle to your live Key. Once the demo credentials are in place, call set_sandbox_mode(True) in ccxt so every request carries the demo header (x-simulated-trading: 1); the REST domain is the same for demo and live, so what separates them is that header and which Key you used, and mixing the two gets you a 50101. Always get the script working on the demo first, confirm orders, cancellations and callbacks all behave, then swap in your live credentials.

How are fees calculated when I place orders via the API?

API orders use the same fee schedule as web and app orders, split by your tier and maker/taker, with exact rates per whatever OKX currently publishes. High-frequency place/cancel loops in a script aren't necessarily free, so read the rules for your tier first.

What do I put in the ccxt password field?

Put in the Passphrase you set when you created the API Key—not your login password, and not the secret. This is OKX's distinctive third credential, and the one beginners easily miss. ccxt names this field password, which makes it easy to enter your login password by mistake and get stuck on authentication errors.

My order script says permission denied—what now?

Most likely you only ticked Read and not Trade when you created the Key. Checking your balance is a read permission; placing orders is a trade permission, and they're granted separately. Go back to API management on OKX, check this Key's permissions, and add Trade. If you set an IP whitelist, also confirm your current outbound IP is on the list.

Once you've cleared the API wall, you'll probably want a concrete strategy to practice on. We suggest starting with the easiest one to grasp, the grid bot, or first using a small tool to work out the parameters and fees before you act. Whichever road you take, remember the order from today's piece: demo first, then small-size live, survive first, talk returns later.