Read-only vs trade permission on an API key
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.
A key that cannot trade cannot be talked into trading — not by a bug, not by a prompt, not by a mislabeled tool. It is the only boundary in the stack enforced by someone other than your own software.
Which is why it is worth knowing how each venue actually implements it, because they are not the same and one of them works backwards from the rest.
Short answer by venue
| Venue | Read-only mechanism | Safe by default? |
|---|---|---|
| Binance | Permission flags on the key; enableReading alone | No — you choose at creation |
| Bybit | Permission scopes on the key | No |
| Alpaca | Access Controls: Read only / Full access / Custom per scope | No |
| IBKR (TWS) | Application setting, not a credential | Yes — Read-Only API is on by default |
| Hyperliquid | No API key at all; agent wallets sign | Structurally, mostly |
Binance
Permissions are flags on the key, readable programmatically via
GET /sapi/v1/account/apiRestrictions, which returns ipRestrict,
enableReading, enableWithdrawals, enableMargin, enableFutures and
others.
Two Binance-specific behaviours matter more than the flags themselves:
Withdrawals require IP restriction. The filter is a precondition for the permission, not an option beside it. A key with no IP whitelist structurally cannot withdraw.
Trading permission expires on unrestricted keys. A key with no IP whitelist has “Enable Spot & Margin Trading” automatically unchecked 90 days after activation. Keys with a whitelist do not expire this way.
The practical effect is that Binance nudges you toward IP-restricted keys whether or not you were planning to bother.
Bybit
Scopes are set on the key. IP binding exists and is enforced — error 10010,
“Unmatched IP, please check your API key’s bound IP addresses”, is its signature.
Permission refusals surface as 10005, “Permission denied, please check your
API key permissions.”
Worth distinguishing from the codes that look similar but are not permission
problems: 10003 is session count on classic accounts and an expired key
under UTA, and 110028 / 100028 are unified-account eligibility rather than
scope.
Alpaca
Alpaca sets permissions at key-generation time through Access Controls, with three levels:
- Read only — view data across all API scopes
- Full access — view and modify across all scopes
- Custom — per-scope choice of Read & Write or Read only
Custom is the useful one: you can leave watchlists writable while trading stays read-only.
OAuth is a separate mechanism with its own scopes, requested in the
authorization URL (scope=account:write trading) and echoed in the token
response. A read-only OAuth integration is achieved by omitting the write
scopes rather than by requesting a read-only one. Alpaca additionally requires
OAuth apps to be approved before they can trade on users’ behalf.
IBKR — the one that works backwards
IBKR does not attach permissions to a credential, because the TWS API does not use one: it is a socket to a logged-in desktop application. The permission is an application setting.
TWS 950 and above has a Read-Only API mode that “allows viewing of market data and account information, but blocks any type of trading activity” — and it is enabled by default.
Find it at Global Configuration → API → Settings. In TWS Classic that is Edit → Global Configuration; in Mosaic, File → Global Configuration or the cog wheel. In IB Gateway: Configure → Settings → API → Settings.
Two consequences worth internalising:
The most common “my orders are being rejected” cause on TWS is this checkbox, not your code. If API orders are failing and everything else works, look here first.
IBKR is the only venue in this comparison where doing nothing leaves you safe. Everywhere else a freshly created trading key is armed the moment it exists. Here the default blocks orders and you must deliberately unblock them.
One related default: “Enable ActiveX and Socket Clients” is off by default in TWS, though IB Gateway accepts socket connections by default. So a fresh TWS install refuses API connections entirely until you enable it.
Hyperliquid — no key to set permissions on
Hyperliquid has no API key. A master account approves an API wallet (agent wallet) to sign on its behalf. The documentation states plainly that “API wallets are only used to sign”, and that querying account data requires passing the master or sub-account’s actual address — the agent’s own address owns nothing.
Can an agent wallet move funds? Hyperliquid does not say, and there is no
prohibition to quote. What its official Python SDK shows is structural: the
fund-moving actions (withdraw3, usdSend, spotSend) are user-signed and
take no account or vault address, while trading actions go through the L1
signing path that does. That address field is how an agent’s signature gets
attributed to the master. Without it, there is no way to express “move the
master account’s funds” in the payload at all.
So the practical answer is that the signing scheme gives an agent wallet no way to express a withdrawal of the master’s funds — a structural property rather than a permission flag, and arguably stronger than a checkbox. But Hyperliquid has not stated it, so verify it against your own setup before relying on it as a boundary.
What to actually do
Start read-only. Most of what people want from programmatic access — reading positions, computing exposure, monitoring — needs no write permission at all.
Separate keys by purpose. One key per consumer means a leak is revocable without collateral damage, and an error tells you which component caused it.
Verify rather than remember. Binance exposes the key’s state over the API. On IBKR, look at the checkbox. On Alpaca, look at the key’s Access Controls. What you configured six months ago is not reliably what is running.
Do not treat a server’s read-only mode as the permission. Some MCP servers and client libraries offer read-only modes, and the good ones are well built. But that is a control inside the component you are bounding. The key permission holds regardless of what your software does.
FAQ
Which venue is safest by default?
IBKR, by a clear margin and somewhat by accident of architecture. Its Read-Only API setting blocks all API trading and is enabled by default, so a fresh setup cannot place orders until you deliberately allow it. Every other venue here issues a key with whatever permissions you selected, active immediately.
Can I make an Alpaca key read-only?
Yes. Generate it with Read only access, or use Custom and set the
trading scope to Read only while leaving other scopes as needed. For OAuth
integrations, the equivalent is omitting trading and account:write from the
requested scope.
Why does my Binance key work for reading but not for trading?
If it has no IP whitelist, the likely cause is the 90-day expiry: Binance automatically unchecks “Enable Spot & Margin Trading” 90 days after activation for keys without IP restriction. Reads keep working, so the symptom is specifically that orders start being refused. Re-enable it and add a whitelist.
How does this work on Hyperliquid, which has no API keys?
Through delegation rather than permissions: a master account approves an agent wallet that can sign on its behalf. The signing scheme means fund-moving actions carry no account address and so cannot be expressed for the master by an agent signature. It behaves like trade-only in practice, but it is a structural property that Hyperliquid has not documented as a guarantee — check it on your own setup.