Scoping an exchange API key for a trading bot: what KuCoin's and Bitget's docs actually say about IP binding, expiry and lost secrets
Disclosure: This post includes affiliate links to KuCoin and Bitget. I may receive compensation if you sign up through them. That doesn't change the doc quotes below, which come straight from each exchange's own pages. N
Disclosure: This post includes affiliate links to KuCoin and Bitget. I may receive compensation if you sign up through them. That doesn't change the doc quotes below, which come straight from each exchange's own pages. Neither exchange is available everywhere (see "Availability" at the end), and I haven't tested either hands-on.
Most "how to create an API key" posts stop at the screenshot of the create button. The part that bites later is quieter: a key that silently loses trade permission after a month, a passphrase nobody wrote down, a withdrawal call that fails because the server's IP changed. I read the current key-management docs for two exchanges that bot builders often wire up, KuCoin (affiliate link) and Bitget (affiliate link), and wrote down the rules that change how you'd deploy a bot. Everything here was checked against the official pages on 13 November 2026.
1. Decide what the key must never do, then pick permissions
Both exchanges split permissions finely enough that a market-data or reporting job doesn't need trading rights.
- KuCoin sub-account keys can be given only these permissions: "General, Spot, Futures, Unified, Margin, InnerTransfer (Flex Transfer)" (KuCoin: add sub-account API).
- Bitget's REST page lists four permission types, Read-Only, Trade, Transfer and Withdraw, and its Unified Trading Account quick start describes trade and management scopes as either read-only or read-and-write (Bitget UTA REST API, Bitget UTA quick start).
A rule I use: one key per job. The price collector gets a read-only key. The execution service gets trade, and nothing that moves funds off the exchange. If something needs withdrawals, it's a separate key, on a separate host, with its own alerting. Bitget lets each UID create "up to 50 API key sets", so you won't run out by splitting.
2. IP binding isn't optional in practice
The two exchanges word this differently, and the difference matters for how you deploy.
Bitget says "it is strongly recommended that you bind an IP address when creating the API Key", and separately that "you can only withdraw coins through a whitelisted IP address" (UTA quick start; UTA REST). So binding is advice for trading keys, but a hard rule for withdrawals. I couldn't find an official figure for the maximum IPs per Bitget key or an expiry for unbound keys on the pages I read; third-party posts quote numbers, but I'm not repeating them.
KuCoin's support article says keys with trading permission that aren't linked to an IP "will be automatically deleted or have their trade permissions disabled after 30 days of inactivity", while "there is no expiration limit for API keys that only have the General permissions" (KuCoin support: API key FAQ). The same article also says "To enable access to permissions, you must add your IP address to the whitelist", which doesn't say exactly which permissions need it, so treat binding as required and you won't be surprised. For sub-account keys, the API reference says "You may add up to 20 IPs."
What this means for deployment:
- Serverless or autoscaling runners don't have a stable egress IP by default. Route the bot through a NAT gateway or a small fixed-IP box before you create the key, not after.
- A paused bot can lose its key. On KuCoin, an unbound trading key that sits idle for 30 days can be disabled or deleted. If you run seasonal strategies, bind the IP or put a calendar reminder on the key.
- Withdrawal automation on Bitget must come from a whitelisted IP, full stop. Plan the host first.
3. Treat the passphrase as unrecoverable
Both exchanges add a passphrase on top of key and secret, and neither will give it back.
- KuCoin's authentication docs say the key, secret and passphrase "can not be recovered once lost" (KuCoin authentication). Sub-account passphrases "Must contain 7β32 characters. Cannot contain any spaces."
- Bitget's quick start says the passphrase "cannot be changed. If it is forgotten or lost, you will need to delete and re-create the API Key."
So store all three values together in your secret manager at creation time, and write the rotation runbook before you need it. Re-creating a key means re-applying the IP allowlist and permissions, and updating every service that uses it.
4. Mind the clock and the signature type
- Bitget: "The request will expire 30 seconds after the timestamp." A container with clock drift will start failing auth before it fails anything else. Run NTP, and log the server-time response on startup.
- Bitget supports HMAC-SHA256 and RSA signatures (the quick start includes an RSA demo). RSA means the exchange never holds your private key, which is worth the extra setup for long-lived production keys.
- KuCoin signs with HMAC-SHA256 and base64, and also expects the passphrase itself to be HMAC-SHA256-encrypted with the API secret ("Encrypt passphrase with HMAC-sha256 via API-Secret").
5. Use expiry as a feature
KuCoin sub-account keys take an expiration option: never (the default, -1), or 30, 90, 180 or 360 days (KuCoin: add sub-account API). Defaulting to "never" is convenient and wrong for most bots. A 90-day expiry plus a rotation job is a cheap way to make sure an old leaked key dies on its own. On Bitget, self-managed API keys for sub-accounts are "disabled by default", so you have to turn that on deliberately in the parent account.
A checklist you can paste into your repo
[ ] One key per job; read-only for data collectors
[ ] No withdraw permission on any key that a trading host can reach
[ ] Fixed egress IP exists BEFORE key creation; IP bound on the key
[ ] KuCoin: idle trading keys reviewed before 30 days of inactivity
[ ] Key, secret AND passphrase stored together in the secret manager
[ ] Rotation runbook written; expiry set (KuCoin sub-keys: 30/90/180/360)
[ ] NTP running; Bitget 30-second request window tested
[ ] Consider RSA signing for long-lived Bitget production keys
None of this is exotic. It's just the set of rules that, if you skip them, turn into a 3 a.m. auth error or a key you can't rotate.
Availability
- KuCoin (affiliate link): not available in the US, Canada (Ontario/BC), France, the Netherlands and other regions restricted under KuCoin's terms (checked 29 October 2026). KuCoin EU's MiCA-authorised entity in Austria had not resumed services as of its 30 June 2026 update, so EU/EEA residents may not be able to sign up. KuCoin's terms don't name the UK, but I haven't confirmed it may serve or be promoted to UK residents. Check KuCoin's current terms for your country first.
- Bitget (affiliate link): not available in the US, Canada, France, Germany, Austria, Japan, the UAE, Singapore, Hong Kong, Thailand and other regions restricted under Bitget's terms (checked 4 November 2026). I found no Bitget entity in the ESMA MiCA register (data as of 5 November 2026). Check Bitget's current terms for your country first.
- Trading digital assets, and especially leveraged derivatives, can lose some or all of the assets committed. This post is about key hygiene, not a recommendation to trade.
Affiliate links: I may earn a commission if you sign up through the KuCoin or Bitget links above.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.