API keys and permissions

Creating a KuCoin API key for Bicrypto — what the API passphrase is and why it is not optional, which permissions each platform feature needs, IP whitelisting, and how to rotate a key without downtime.

5 min readUpdated 3 August 2026kucoin, api-key, passphrase, permissions, security

A KuCoin API credential is three values, not two. Getting that wrong is the single most common failure on this product, and the platform's own error messages point you at the wrong two.

The passphrase

When you create an API key on KuCoin you are asked to invent an API passphrase. It is not generated for you, it is not your login password, and it is not your trading password. KuCoin never shows it to you again. If you lose it, the only remedy is to delete the key and create a new one.

It is a real part of the signature, not a label. On KuCoin's v2 keys the passphrase is HMAC-SHA256'd with your API secret and sent as the KC-API-PASSPHRASE header on every private request. A wrong passphrase is cryptographically indistinguishable from a wrong secret, which is why the platform reports both as "check your API key and secret".

Bicrypto reads it from:

APP_KUCOIN_API_PASSPHRASE="the_passphrase_you_invented"

The secret is shown once. The passphrase is shown never — you typed it, so KuCoin assumes you have it. Losing either one means a new key, a new .env edit and a backend restart.

Creating the key

Follow KuCoin's own guide for the current UI — KuCoin API creation guide — the labels move around. What matters for this integration:

  1. Create an API-trading key, not a broker or affiliate key.

  2. Name it for this install. If you run staging and production against the same KuCoin account, one key per install, so you can revoke one without taking the other down.

  3. Set the API passphrase. Save it immediately.

  4. Grant the permissions listed below. Read-only is not enough for a platform that has to move money.

  5. Whitelist your server's outbound IP. See the section on this below — the address to whitelist is not always the one you think.

  6. Complete verification with your trading password, email code and 2FA.

  7. Copy the key and secret straight into .env, then restart the backend.

Which permissions the platform actually needs

Each of these maps to a code path, and turning one off disables that path without disabling anything else. Grant only what you intend to use.

KuCoin permission Needed for What breaks without it
General fetchBalance in the verification round trip, the admin balance screen, the fee comparison screen Verification never returns green; /admin/finance/exchange/balance errors
Spot Trading createOrder and fetchOrder on the user spot order path, and the reconciliation job that settles orders placed while the user's tab was closed Users can browse markets but every order placement fails
Transfer The main → trade internal transfer run after every credited deposit and before every withdrawal Deposits still credit, but withdrawals fail at the first step with "Transfer to trade account failed"
Withdrawal withdraw and fetchWithdrawals on both the user and the admin-approval withdrawal paths Withdrawals fail after the user's balance has already been debited; the reconciliation job then has to refund them

Deposit address generation and deposit detection use private read calls that sit under the general/account scope — the same one the verification call exercises.

A key with Withdrawal enabled can move funds off your KuCoin account. If it leaks, an IP whitelist is the only thing standing between an attacker and your float. If you settle withdrawals manually instead, leave Withdrawal off — the platform will fail the automated path loudly rather than silently mis-paying.

IP whitelisting

Whitelist the address KuCoin sees, which is not necessarily the address your control panel shows.

  • No proxy configured. The backend connects over an HTTPS agent pinned to family: 4, so KuCoin sees your server's IPv4 address even on a dual-stack box. Whitelist that.
  • Proxy configured. Every call, public and private, goes through the proxy. Whitelist the proxy's exit address, not the app server's. Whitelisting the app server in this configuration will look like a silent authentication failure.

Confirm from the app server itself rather than from your laptop:

curl -4 https://api.ipify.org && echo

If you later add or change a proxy, the whitelist has to change with it. Saving a proxy evicts the cached KuCoin client, so the very next call goes out from the new address.

Rotating a key

Rotation is not zero-downtime — the credentials are read once, when the client is first built, and the built client is cached for the life of the process.

  1. Create the replacement key on KuCoin with the same permissions and the same IP whitelist. Give it a new passphrase.

  2. Edit all three APP_KUCOIN_* values in .env together. A half-rotated credential set behaves exactly like a wrong passphrase.

  3. Restart the backend. There is no reload path for these.

  4. Verify from /admin/finance/exchange.

  5. Only then delete the old key on KuCoin.

If you rotate and the platform still authenticates with the old key, you are looking at a stale process — check that the restart actually replaced the backend rather than leaving the previous instance holding the port.

When credentials go wrong at runtime

Two behaviours are worth knowing in advance, because both are quiet.

Repeated failures stick. After three consecutive initialisation failures, ExchangeManager stops trying for 30 minutes and returns nothing during that window. Correcting .env does not shorten the wait; restarting the backend does.

A bad credential degrades rather than stops. If the client can be built but KuCoin rejects the signed calls inside loadMarkets(), the platform falls back to an unauthenticated KuCoin instance and logs:

Falling back to an unauthenticated kucoin instance — authenticated data
(deposit/withdraw networks, balances) will be unavailable until valid API
credentials are configured.

Public data keeps working, which is why nobody notices until a user asks where their deposit address is. Grep for that line whenever the platform "mostly" works.

What users see when it fails

Error text that reaches an end user is scrubbed: the strings kucoin, binance and okx are replaced with *** before the message leaves the backend, and the withdrawal path replaces exchange errors wholesale with "Withdrawal request failed. Please try again or contact support."

So a user report will never name the cause. The real error is in the backend log and in the admin action log for that request — start there, not from the screenshot.