Back to KuCoin JavaScript SDK
KuCoin APISpotMarginFuturesClassic WebSocketWebSocket APIEU and AU

KuCoin API JavaScript Tutorial for Node.js

Build KuCoin integrations with Classic REST API clients, public and private WebSockets, safe order tests, WebSocket API commands, regional routing, and proxy support.

first-kucoin-api-call.js
public REST API
import { SpotClient } from 'kucoin-api';

const client = new SpotClient();

async function main() {
  try {
    const response = await client.getServerTime();
    console.log('Server time:', response.data);
  } catch (error) {
    console.error('Server time request failed:', error);
  }

  try {
    const response = await client.getSymbol({
      symbol: 'BTC-USDT',
    });
    console.log('BTC-USDT metadata:', response.data);
  } catch (error) {
    console.error('Symbol request failed:', error);
  }

  try {
    const response = await client.getTicker({
      symbol: 'BTC-USDT',
    });
    console.log('BTC-USDT ticker:', response.data);
  } catch (error) {
    console.error('Ticker request failed:', error);
  }

  try {
    const response = await client.getOrderBookLevel20({
      symbol: 'BTC-USDT',
    });
    console.log('Best bid:', response.data.bids[0]);
    console.log('Best ask:', response.data.asks[0]);
  } catch (error) {
    console.error('Order book request failed:', error);
  }

  try {
    const response = await client.getKlines({
      symbol: 'BTC-USDT',
      type: '1hour',
    });
    console.log('Latest candle:', response.data[0]);
  } catch (error) {
    console.error('Candles request failed:', error);
  }
}

main();

API surface map

Choose the KuCoin client for the job

Use the focused Classic clients first, then evaluate newer surfaces only when they match the account and deployment.

Your app

Bot, dashboard, worker, tool

Any Node.js or JavaScript-compatible service that needs KuCoin market data, account state, order management, or reconciliation.

npm package

npm install kucoin-api

SpotClient

Classic Spot, Margin, funding, transfer, Earn, and Convert REST API calls

FuturesClient

Classic Futures market, account, order, position, and funding REST API calls

WebsocketClient

Classic and Pro public and private WebSocket subscriptions

WebsocketAPIClient

Awaitable Spot, Margin, and Futures order commands

BrokerClient

Broker subaccount, transfer, deposit, withdrawal, and rebate calls

UnifiedAPIClient

Developing Unified Account REST API surface

KuCoin API

Spot and Margin REST API calls

Futures REST API calls

Public and private WebSocket streams

WebSocket API order commands

Broker and developing Unified endpoints

Request routing

Product, account, contract, connection, and region are separate choices

Keep these values explicit so each request reaches the intended KuCoin API surface and account.

Spot symbol

symbol: 'BTC-USDT'

Select a Spot or Margin trading pair.

Futures contract

symbol: 'XBTUSDTM'

Select the exact Futures contract and its sizing rules.

Account type

type: 'trade'

Select the account used by a balance or transfer request.

Client order ID

clientOid

Give an application-owned order a stable identifier.

WebSocket connection

WS_KEY_MAP.spotPublicV1

Route a subscription or command to the correct connection.

API region

apiRegion: 'EU'

Route supported REST API calls and token-based streams for the account region.

What this tutorial covers

What to get right in a KuCoin integration

Start with Classic public data, then add credentials, private state, safe order tests, network configuration, and recovery.

REST API clients and response envelopes

Choose SpotClient or FuturesClient, then read successful endpoint data from response.data.

Public and private Classic streams

Subscribe through WebsocketClient and select the correct product connection with WS_KEY_MAP.

Safe tests and live commands

Use REST API order-test methods first and guard the live WebSocket API example behind an explicit opt-in.

Regions, proxies, and recovery

Keep account region and network path explicit, then reload private state after stream gaps.

Start building

First REST API calls, streams, order tests, and WebSocket API commands

Run one focused JavaScript example at a time, then add recovery and production controls around the same clients.

import { SpotClient } from 'kucoin-api'; const client = new SpotClient(); async function main() {  try {    const response = await client.getServerTime();    console.log('Server time:', response.data);  } catch (error) {    console.error('Server time request failed:', error);  }   try {    const response = await client.getSymbol({      symbol: 'BTC-USDT',    });    console.log('BTC-USDT metadata:', response.data);  } catch (error) {    console.error('Symbol request failed:', error);  }   try {    const response = await client.getTicker({      symbol: 'BTC-USDT',    });    console.log('BTC-USDT ticker:', response.data);  } catch (error) {    console.error('Ticker request failed:', error);  }   try {    const response = await client.getOrderBookLevel20({      symbol: 'BTC-USDT',    });    console.log('Best bid:', response.data.bids[0]);    console.log('Best ask:', response.data.asks[0]);  } catch (error) {    console.error('Order book request failed:', error);  }   try {    const response = await client.getKlines({      symbol: 'BTC-USDT',      type: '1hour',    });    console.log('Latest candle:', response.data[0]);  } catch (error) {    console.error('Candles request failed:', error);  }} main();

Workflow diagrams

REST API, WebSocket stream, and WebSocket API workflows

REST API results, stream updates, and WebSocket API command responses carry different information.

REST API request flow

Choose the product client and region, then let the SDK sign private requests and return KuCoin's response envelope.

Choose client and regionYour code
Call an SDK methodYour code
Route and signSDK handles
Receive code and dataKuCoin
Use endpoint dataYour code

Classic WebSocket subscription flow

Choose a topic and wsKey, let the SDK obtain a connection token, then process acknowledgements and updates.

Choose topic and wsKeyYour code
Call subscribeYour code
Obtain token and connectSDK handles
Receive welcome and acknowledgementEvent
Process update eventsYour code

WebSocket API command flow

Await the command response, then confirm final order state through a private stream or REST API query.

Guard the live actionYour code
Await order commandYour code
Match request and responseSDK handles
Inspect code and dataYour code
Confirm final order stateYour code

Production rollout

Before a KuCoin integration trades unattended

Credentials, response handling, product sizing, acknowledgements, reconnect recovery, region, and network behavior must all be predictable.

Keep API keys server-side and grant only the permissions each process needs.

Keep symbol, account type, position mode, wsKey, and apiRegion explicit in order code and logs.

Set clientOid on application-owned orders so retries and restarts can reconcile them.

Read successful endpoint data from data and preserve KuCoin error details when a request fails.

Treat a WebSocket API response as a command result, then confirm final order state.

Reload balances, positions, open orders, and fills after a private stream gap.

Keep the system clock synchronized and respect current KuCoin rate limits.

Monitor proxy reachability, latency, and egress IP when a proxy is enabled.

Choose your path

Jump to the KuCoin workflow you are building

Browse all examples

Start with REST API calls

Make public market calls, add credentials, then inspect balances and order state.

Open section

Stream live data

Subscribe to public and private Classic Spot and Futures channels.

Open section

Send WebSocket commands

Use WebsocketAPIClient for promise-based Spot, Margin, and Futures order commands.

Open section

Configure networking

Select the account region, then add an HTTP or SOCKS proxy agent when required.

Open section

Build around KuCoin products and account state

This tutorial covers the KuCoin API pieces developers usually need first: Classic REST API calls, public and private streams, safe order tests, WebSocket API commands, regional routing, proxies, and reconnect recovery.

This tutorial uses kucoin-api, Siebly's Node.js and JavaScript SDK for KuCoin. It covers Classic Spot and Futures REST API calls, public and private WebSockets, safe order tests, WebSocket API commands, regional routing, and proxies.

The SDK handles private request signing, connection-token requests, product-specific WebSocket routing, heartbeats, reconnects, resubscriptions, and WebSocket API response matching.

Key links

Why use kucoin-api?

Private KuCoin REST API requests require an API key, timestamp, HMAC signature, encrypted API passphrase, and API key version. Classic WebSocket connections use connection tokens, while subscriptions and WebSocket API commands must reach the correct product connection.

kucoin-api handles those mechanics and provides a focused client for each job:

ClientUse it for
SpotClientClassic Spot, Margin, funding, transfer, Earn, and Convert REST API calls
FuturesClientClassic Futures market, account, order, position, and funding REST API
WebsocketClientClassic and Pro public and private WebSocket subscriptions
WebsocketAPIClientPromise-based Spot, Margin, and Futures order commands over WebSocket
BrokerClientBroker subaccounts, transfers, deposits, withdrawals, and rebates
UnifiedAPIClientDeveloping Unified Account REST API endpoints

Start with the Classic clients unless the developing Unified Account or Pro API is specifically required.

Install the SDK

npm install kucoin-api

Every example below is JavaScript and imports directly from kucoin-api.

Create KuCoin API keys

Public market data does not require credentials. Private REST API calls, private streams, REST API order tests, and WebSocket API commands require an API key, secret, and API passphrase.

Create and manage keys from the KuCoin API management page. Save all three values when creating the key:

  • KUCOIN_API_KEY
  • KUCOIN_API_SECRET
  • KUCOIN_API_PASSPHRASE

The API passphrase is the value chosen when creating the API key. It is not the KuCoin account password.

Grant only the permissions the application needs:

PermissionTypical use
GeneralRead account, order, and ledger information
SpotPlace, modify, and cancel Spot orders
MarginPlace and manage Margin orders
FuturesPlace orders and manage Futures positions
EarnSubscribe to and redeem eligible Earn products
WithdrawalCreate and manage withdrawals; requires an IP restriction

Use a General-only key while building account views and recovery logic. Add Spot or Futures permission only when testing order placement. Nothing in this tutorial requires Withdrawal permission.

Keep API keys in a server-side secret manager or deployment environment. Never put them in browser code or log them.

KuCoin products and request vocabulary

Several fields determine which product, account, and connection a request uses:

Field or valueExampleMeaning
Spot symbolBTC-USDTHyphen-separated Spot or Margin trading pair
Futures symbolXBTUSDTMExact Futures contract identifier
Successful REST API response{ code: '200000', data: endpointData }KuCoin response envelope; endpoint data is under data
Spot account typetradeTrading account used by most current Spot users
Client order IDclientOidApplication-owned custom order ID
Futures size1Number of contracts or lots, not an amount of BTC or USDT
Futures multiplierContract metadataUnderlying amount represented by one contract
Futures lotSize and tickSizeContract metadataValid size and price increments
Position mode0 or 1One-way mode or hedge mode
WebSocket keyWS_KEY_MAP.spotPublicV1WebSocket key selecting a connection
API regionglobal, EU, or AUAccount region used for supported routing

KuCoin's current preferred Spot order methods contain HF, such as submitHFOrder() and getHFActiveOrdersPaginated(). These map to the current high-frequency Spot API paths. New users normally keep their trading account type as trade; trade_hf is a compatibility case for some older accounts.

Start building: first calls and streams

Run each example on its own. Begin with public data, then add credentials, private state, safe order tests, and live streams.

1. Make public REST API calls

Public calls need no API key. Every successful KuCoin REST API response contains code and data.

import { SpotClient } from 'kucoin-api';

const client = new SpotClient();

async function main() {
  try {
    const response = await client.getServerTime();
    console.log('Server time:', response.data);
  } catch (error) {
    console.error('Server time request failed:', error);
  }

  try {
    const response = await client.getSymbol({
      symbol: 'BTC-USDT',
    });
    console.log('BTC-USDT metadata:', response.data);
  } catch (error) {
    console.error('Symbol request failed:', error);
  }

  try {
    const response = await client.getTicker({
      symbol: 'BTC-USDT',
    });
    console.log('BTC-USDT ticker:', response.data);
  } catch (error) {
    console.error('Ticker request failed:', error);
  }

  try {
    const response = await client.getOrderBookLevel20({
      symbol: 'BTC-USDT',
    });
    console.log('Best bid:', response.data.bids[0]);
    console.log('Best ask:', response.data.asks[0]);
  } catch (error) {
    console.error('Order book request failed:', error);
  }

  try {
    const response = await client.getKlines({
      symbol: 'BTC-USDT',
      type: '1hour',
    });
    console.log('Latest candle:', response.data[0]);
  } catch (error) {
    console.error('Candles request failed:', error);
  }
}

main();

Server time is a number. Symbol, ticker, and order-book data are objects. Candles are arrays of tuples. A Spot candle contains:

[
  startTime,
  open,
  close,
  high,
  low,
  volume,
  turnover
]

Prices and quantities are commonly strings. Keep them as strings when passing values back to KuCoin, and convert them deliberately when performing calculations.

2. Make private REST API calls

Private methods use the same client with credentials. The SDK signs each request and returns KuCoin's response envelope.

import { SpotClient } from 'kucoin-api';

const client = new SpotClient({
  apiKey: process.env.KUCOIN_API_KEY,
  apiSecret: process.env.KUCOIN_API_SECRET,
  apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
});

async function main() {
  if (
    !process.env.KUCOIN_API_KEY ||
    !process.env.KUCOIN_API_SECRET ||
    !process.env.KUCOIN_API_PASSPHRASE
  ) {
    console.error(
      'Set KUCOIN_API_KEY, KUCOIN_API_SECRET, and KUCOIN_API_PASSPHRASE.',
    );
    return;
  }

  try {
    const response = await client.getBalances({
      type: 'trade',
    });
    console.log('Spot trading balances:', response.data);
  } catch (error) {
    console.error('Balance request failed:', error);
  }

  try {
    const response = await client.getHFActiveOrdersPaginated({
      symbol: 'BTC-USDT',
      pageNum: 1,
      pageSize: 20,
    });
    console.log('Open BTC-USDT orders:', response.data.items);
  } catch (error) {
    console.error('Open-order request failed:', error);
  }

  try {
    const response = await client.getHFFilledOrders({
      symbol: 'BTC-USDT',
      limit: 20,
    });
    console.log('Recent BTC-USDT fills:', response.data.items);
  } catch (error) {
    console.error('Fill-history request failed:', error);
  }
}

main();

The client throws when KuCoin returns a non-success business code. Parsed errors include the HTTP status, response body, response headers, and request context without exposing the API key, secret, or passphrase.

3. Subscribe to public Classic WebSocket streams

Classic WebSocket subscriptions use a topic and an explicit wsKey. The SDK requests the required connection token, opens the correct connection, keeps it alive, and resubscribes after a reconnect.

import { WebsocketClient, WS_KEY_MAP } from 'kucoin-api';

const ws = new WebsocketClient();

ws.on('open', ({ wsKey }) => {
  console.log('WebSocket opened:', wsKey);
});

ws.on('response', (response) => {
  console.log('WebSocket response:', response.wsKey, response.type);
});

ws.on('update', (update) => {
  console.log('WebSocket update:', update.wsKey, update.topic, update.data);
});

ws.on('reconnect', ({ wsKey }) => {
  console.log('Reconnecting:', wsKey);
});

ws.on('reconnected', ({ wsKey }) => {
  console.log('Reconnected:', wsKey);
});

ws.on('close', ({ wsKey }) => {
  console.log('WebSocket closed:', wsKey);
});

ws.on('exception', (error) => {
  console.error('WebSocket exception:', error);
});

try {
  ws.subscribe('/market/ticker:BTC-USDT', WS_KEY_MAP.spotPublicV1);
} catch (error) {
  console.error('Spot subscription failed:', error);
}

try {
  ws.subscribe('/contractMarket/tickerV2:XBTUSDTM', WS_KEY_MAP.futuresPublicV1);
} catch (error) {
  console.error('Futures subscription failed:', error);
}

process.once('SIGINT', () => {
  ws.closeAll();
});

A welcome response means the connection is ready. An ack confirms the subscription acknowledgement. Market data arrives separately through update.

4. Subscribe to private Classic WebSocket streams

Private subscriptions use the same client with credentials. Spot and Futures topics use separate connections.

import { WebsocketClient, WS_KEY_MAP } from 'kucoin-api';

function main() {
  if (
    !process.env.KUCOIN_API_KEY ||
    !process.env.KUCOIN_API_SECRET ||
    !process.env.KUCOIN_API_PASSPHRASE
  ) {
    console.error(
      'Set KUCOIN_API_KEY, KUCOIN_API_SECRET, and KUCOIN_API_PASSPHRASE.',
    );
    return;
  }

  const ws = new WebsocketClient({
    apiKey: process.env.KUCOIN_API_KEY,
    apiSecret: process.env.KUCOIN_API_SECRET,
    apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
  });

  ws.on('open', ({ wsKey }) => {
    console.log('Private WebSocket opened:', wsKey);
  });

  ws.on('response', (response) => {
    console.log('Private WebSocket response:', response.wsKey, response.type);
  });

  ws.on('update', (update) => {
    console.log('Private update:', update.wsKey, update.topic, update.data);
  });

  ws.on('reconnected', ({ wsKey }) => {
    console.log('Private WebSocket reconnected:', wsKey);
  });

  ws.on('exception', (error) => {
    console.error('Private WebSocket exception:', error);
  });

  try {
    ws.subscribe(
      ['/spotMarket/tradeOrdersV2', '/account/balance'],
      WS_KEY_MAP.spotPrivateV1,
    );
  } catch (error) {
    console.error('Private Spot subscription failed:', error);
  }

  try {
    ws.subscribe(
      [
        '/contractMarket/tradeOrders:XBTUSDTM',
        '/contractAccount/wallet',
        '/contract/position:XBTUSDTM',
      ],
      WS_KEY_MAP.futuresPrivateV1,
    );
  } catch (error) {
    console.error('Private Futures subscription failed:', error);
  }

  process.once('SIGINT', () => {
    ws.closeAll();
  });
}

main();

Private order updates provide private stream confirmation after an order command. Keep the wsKey with every event so Spot and Futures state cannot be mixed.

5. Validate a Spot order with the REST API

KuCoin's official Spot test-order endpoint validates authentication and order parameters without entering the matching engine. The returned order ID is only part of the test response and cannot be queried or cancelled.

This example fetches current metadata and the ticker before deriving a size that meets the base and quote minimums.

import { SpotClient } from 'kucoin-api';

const client = new SpotClient({
  apiKey: process.env.KUCOIN_API_KEY,
  apiSecret: process.env.KUCOIN_API_SECRET,
  apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
});

async function main() {
  if (
    !process.env.KUCOIN_API_KEY ||
    !process.env.KUCOIN_API_SECRET ||
    !process.env.KUCOIN_API_PASSPHRASE
  ) {
    console.error(
      'Set KUCOIN_API_KEY, KUCOIN_API_SECRET, and KUCOIN_API_PASSPHRASE.',
    );
    return;
  }

  let symbol;

  try {
    const response = await client.getSymbol({
      symbol: 'BTC-USDT',
    });
    symbol = response.data;
  } catch (error) {
    console.error('Symbol request failed:', error);
    return;
  }

  let ticker;

  try {
    const response = await client.getTicker({
      symbol: 'BTC-USDT',
    });
    ticker = response.data;
  } catch (error) {
    console.error('Ticker request failed:', error);
    return;
  }

  const priceNumber = Number(ticker.bestBid);
  const baseIncrement = Number(symbol.baseIncrement);
  const minimumSize = Math.max(
    Number(symbol.baseMinSize),
    Number(symbol.minFunds) / priceNumber,
  );

  if (
    !symbol.enableTrading ||
    !Number.isFinite(priceNumber) ||
    priceNumber <= 0 ||
    !Number.isFinite(baseIncrement) ||
    baseIncrement <= 0 ||
    !Number.isFinite(minimumSize)
  ) {
    console.error('Required BTC-USDT market metadata is unavailable.');
    return;
  }

  const decimals = (symbol.baseIncrement.split('.')[1] || '').length;
  const sizeNumber = Math.ceil(minimumSize / baseIncrement) * baseIncrement;
  const size = sizeNumber.toFixed(decimals);

  try {
    const response = await client.submitHFOrderTest({
      clientOid: client.generateNewOrderID(),
      symbol: 'BTC-USDT',
      side: 'buy',
      type: 'limit',
      price: ticker.bestBid,
      size,
      timeInForce: 'GTC',
      postOnly: true,
    });
    console.log('Spot order test:', response);
  } catch (error) {
    console.error('Spot order test failed:', error);
  }
}

main();

The test endpoint is suitable for checking credentials, Spot permission, request signing, and order fields. It does not test matching, fills, cancellation, or private order updates.

6. Validate a Futures order with the REST API

The official Futures test-order endpoint follows live-order validation without entering the matching engine. A Futures size is a contract count, so fetch the contract before using lotSize, tickSize, multiplier, and supported margin modes.

import { FuturesClient } from 'kucoin-api';

const client = new FuturesClient({
  apiKey: process.env.KUCOIN_API_KEY,
  apiSecret: process.env.KUCOIN_API_SECRET,
  apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
});

async function main() {
  if (
    !process.env.KUCOIN_API_KEY ||
    !process.env.KUCOIN_API_SECRET ||
    !process.env.KUCOIN_API_PASSPHRASE
  ) {
    console.error(
      'Set KUCOIN_API_KEY, KUCOIN_API_SECRET, and KUCOIN_API_PASSPHRASE.',
    );
    return;
  }

  let contract;

  try {
    const response = await client.getSymbol({
      symbol: 'XBTUSDTM',
    });
    contract = response.data;
  } catch (error) {
    console.error('Contract request failed:', error);
    return;
  }

  let ticker;

  try {
    const response = await client.getTicker({
      symbol: 'XBTUSDTM',
    });
    ticker = response.data;
  } catch (error) {
    console.error('Futures ticker request failed:', error);
    return;
  }

  let positionMode;

  try {
    const response = await client.getPositionMode();
    positionMode = response.data.positionMode;
  } catch (error) {
    console.error('Position-mode request failed:', error);
    return;
  }

  if (
    contract.status !== 'Open' ||
    !Number.isFinite(contract.lotSize) ||
    contract.lotSize <= 0 ||
    !ticker.bestBidPrice
  ) {
    console.error('Required XBTUSDTM contract metadata is unavailable.');
    return;
  }

  console.log('Contract multiplier:', contract.multiplier);
  console.log('Price increment:', contract.tickSize);
  console.log('Contract lot size:', contract.lotSize);

  try {
    const response = await client.submitNewOrderTest({
      clientOid: client.generateNewOrderID(),
      symbol: 'XBTUSDTM',
      side: 'buy',
      type: 'limit',
      price: ticker.bestBidPrice,
      size: contract.lotSize,
      leverage: 1,
      marginMode: contract.supportCross ? 'CROSS' : 'ISOLATED',
      positionSide: positionMode === 1 ? 'LONG' : 'BOTH',
      timeInForce: 'GTC',
      postOnly: true,
    });
    console.log('Futures order test:', response);
  } catch (error) {
    console.error('Futures order test failed:', error);
  }
}

main();

In one-way mode, use positionSide: 'BOTH'. Hedge mode separates LONG and SHORT. The contract multiplier determines the underlying exposure represented by each contract. The test order does not enter the matching engine and cannot be queried or cancelled.

7. Place and cancel a live Spot order through the WebSocket API

KuCoin does not provide a WebSocket API test-order command. This example can place a real order and therefore does nothing unless KUCOIN_PLACE_LIVE_ORDER=true is set.

It reads current Spot metadata, derives the minimum valid size, submits a post-only buy at the current best bid, cancels it, and queries the final state through the REST API. A post-only order can still fill after it rests on the book, so use a dedicated key and only fund the account with an amount suitable for testing.

import { SpotClient, WebsocketAPIClient, WS_KEY_MAP } from 'kucoin-api';

async function main() {
  if (process.env.KUCOIN_PLACE_LIVE_ORDER !== 'true') {
    console.error(
      'Set KUCOIN_PLACE_LIVE_ORDER=true to run this live order example.',
    );
    return;
  }

  if (
    !process.env.KUCOIN_API_KEY ||
    !process.env.KUCOIN_API_SECRET ||
    !process.env.KUCOIN_API_PASSPHRASE
  ) {
    console.error(
      'Set KUCOIN_API_KEY, KUCOIN_API_SECRET, and KUCOIN_API_PASSPHRASE.',
    );
    return;
  }

  const credentials = {
    apiKey: process.env.KUCOIN_API_KEY,
    apiSecret: process.env.KUCOIN_API_SECRET,
    apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
  };

  const rest = new SpotClient(credentials);
  const wsApi = new WebsocketAPIClient(credentials);

  let symbol;

  try {
    const response = await rest.getSymbol({
      symbol: 'BTC-USDT',
    });
    symbol = response.data;
  } catch (error) {
    console.error('Symbol request failed:', error);
    return;
  }

  let ticker;

  try {
    const response = await rest.getTicker({
      symbol: 'BTC-USDT',
    });
    ticker = response.data;
  } catch (error) {
    console.error('Ticker request failed:', error);
    return;
  }

  const priceNumber = Number(ticker.bestBid);
  const baseIncrement = Number(symbol.baseIncrement);
  const minimumSize = Math.max(
    Number(symbol.baseMinSize),
    Number(symbol.minFunds) / priceNumber,
  );

  if (
    !symbol.enableTrading ||
    !Number.isFinite(priceNumber) ||
    priceNumber <= 0 ||
    !Number.isFinite(baseIncrement) ||
    baseIncrement <= 0 ||
    !Number.isFinite(minimumSize)
  ) {
    console.error('Required BTC-USDT market metadata is unavailable.');
    return;
  }

  const decimals = (symbol.baseIncrement.split('.')[1] || '').length;
  const sizeNumber = Math.ceil(minimumSize / baseIncrement) * baseIncrement;
  const size = sizeNumber.toFixed(decimals);
  const clientOid = rest.generateNewOrderID();
  let orderId;

  try {
    const response = await wsApi.submitNewSpotOrder(
      {
        clientOid,
        symbol: 'BTC-USDT',
        side: 'buy',
        type: 'limit',
        price: ticker.bestBid,
        size,
        timeInForce: 'GTC',
        postOnly: true,
      },
      WS_KEY_MAP.wsApiSpotV1,
    );
    console.log('WebSocket API response code:', response.code);
    console.log('WebSocket API timing:', response.inTime, response.outTime);
    orderId = response.data.orderId;
  } catch (error) {
    console.error('WebSocket API order failed:', error);
    wsApi.getWSClient().closeAll();
    return;
  }

  try {
    const response = await wsApi.cancelSpotOrder(
      {
        orderId,
        symbol: 'BTC-USDT',
      },
      WS_KEY_MAP.wsApiSpotV1,
    );
    console.log('Cancellation response:', response.data);
  } catch (error) {
    console.error('WebSocket API cancellation failed:', error);
  }

  try {
    const response = await rest.getHFOrderDetailsByOrderId({
      orderId,
      symbol: 'BTC-USDT',
    });
    console.log('Final REST API order state:', response.data);
  } catch (error) {
    console.error('Final order query failed:', error);
  } finally {
    wsApi.getWSClient().closeAll();
  }
}

main();

The WebSocket API response confirms the command result, not whether the order later filled or reached its final cancellation state. Treat it as pending confirmation, then use a private order stream and a REST API query to confirm the final state.

Work with the KuCoin REST API

Understand response envelopes

Successful KuCoin REST API calls resolve to:

const response = {
  code: '200000',
  data: {},
};

The SDK returns this envelope and throws when KuCoin returns a non-success business code. The shape inside data depends on the endpoint.

Methoddata shape
SpotClient.getServerTime()Timestamp number
SpotClient.getSymbol()Spot symbol object
SpotClient.getTicker()Spot ticker object
SpotClient.getTickers()Object containing time and a ticker array
SpotClient.getOrderBookLevel20()Object containing tuple-array bids and asks
SpotClient.getKlines()Array of candle tuples
FuturesClient.getSymbol()Futures contract object
FuturesClient.getTicker()Futures ticker object
FuturesClient.getPositions()Array of position objects

Check the complete endpoint map and official KuCoin documentation before reading an unfamiliar response.

Read Spot account and order state

These current Spot methods form a useful account state baseline:

StateSDK method
Trading balancesgetBalances({ type: 'trade' })
Account ledgersgetTransactions() or getHFTransactions()
Open ordersgetHFActiveOrdersPaginated()
Completed ordersgetHFCompletedOrders()
Recent fillsgetHFFilledOrders()
Order by IDgetHFOrderDetailsByOrderId()
Order by client IDgetHFOrderDetailsByClientOid()
Dead-man-switch statuscancelHFOrderAutoSettingQuery()

The unpaginated getHFActiveOrders() method is deprecated. Use getHFActiveOrdersPaginated() in new code.

Work with Futures

Use FuturesClient for Classic Futures market data, account state, orders, positions, margin, and funding:

WorkflowRepresentative methods
Contract metadatagetSymbol(), getSymbols()
Market datagetTicker(), getKlines(), getPartOrderBookLevel2Depth20()
AccountgetBalance(), getTransactions()
OrderssubmitOrder(), getOrders(), getRecentOrders(), getFills()
PositionsgetPositionV2(), getPositions(), getHistoryPositions()
Margin and leveragegetMarginMode(), updateMarginMode(), changeCrossMarginLeverage()
Position modegetPositionMode(), updatePositionMode()
FundinggetFundingRate(), getFundingRates(), getFundingHistory()
TransferssubmitTransferIn(), submitTransferOut(), getTransfers()

Always fetch contract metadata before sizing a Futures order. Use multiplier, lotSize, tickSize, maxOrderQty, maxLeverage, and supportCross from the returned contract.

Explore other REST API groups

Start with read methods and check account eligibility and API permissions before calling a write method.

Product groupRepresentative SDK methods
Spot and funding accountsgetBalances(), getTransactions(), getTransferable()
TransferssubmitFlexTransfer(), getTransferable()
SubaccountsgetSubAccountsV2(), getSubAccountBalance(), getSubAccountBalancesV2()
MargingetMarginBalance(), getHFActiveMarginOrders(), getHFMarginFills(), submitHFMarginOrderTest()
Margin lendinggetLendingCurrencyV3(), getLendingInterestRateV3()
ConvertgetConvertSymbol(), getConvertQuote(), getConvertOrderHistory()
EarngetEarnSavingsProducts(), getEarnStakingProducts()
Structured productsgetDualInvestmentProducts(), getStructuredProductOrders()
AffiliategetAffiliateInvitees(), getAffiliateCommission()
Futures copy tradingsubmitCopyTradeOrderTest(), getCopyTradeMaxOpenSize()
BrokergetBrokerInfo(), getSubAccounts(), getTransferHistory()

Withdrawals and API-key management are intentionally omitted from runnable examples. They require broader permissions and carry a larger operational risk.

Build with Classic WebSocket streams

Classic WebSockets are the production-oriented default in this guide. Every subscription combines a topic with a wsKey. The official Classic WebSocket introduction covers connection tokens, welcome messages, and heartbeats.

Choose the correct WebSocket key

ConnectionSDK key
Public Spot and MarginWS_KEY_MAP.spotPublicV1
Private Spot and MarginWS_KEY_MAP.spotPrivateV1
Public FuturesWS_KEY_MAP.futuresPublicV1
Private FuturesWS_KEY_MAP.futuresPrivateV1
Spot WebSocket APIWS_KEY_MAP.wsApiSpotV1
Futures WebSocket APIWS_KEY_MAP.wsApiFuturesV1

Useful Classic topics include:

ProductPublic topicsPrivate topics
Spot/market/ticker, /spotMarket/level2Depth5, /market/candles, /market/match/spotMarket/tradeOrdersV2, /account/balance, /spotMarket/advancedOrders
Margin/indicator/index, /indicator/markPrice/margin/position, /margin/isolatedPosition
Futures/contractMarket/tickerV2, /contractMarket/level2Depth5, /contractMarket/execution/contractMarket/tradeOrders, /contractAccount/wallet, /contract/position

A Spot symbol uses BTC-USDT, while a Futures topic uses a contract such as XBTUSDTM. Do not route a topic based only on the underlying asset.

Treat responses and updates differently

The response event includes connection messages and request acknowledgements. For Classic streams:

  • welcome means the connection is ready.
  • ack confirms that KuCoin accepted a subscription request.
  • update carries market or account data.

The SDK adds wsKey to emitted events. Store it with the topic and payload so data from separate connections remains distinguishable.

Recover after a reconnect

The SDK reconnects and restores cached subscriptions. A connection gap can still hide balance, order, fill, or position changes. Reload the affected state from the REST API after reconnected.

This example replaces local Spot state only after balances, open orders, and recent fills all reload successfully:

import { SpotClient, WebsocketClient, WS_KEY_MAP } from 'kucoin-api';

const credentials = {
  apiKey: process.env.KUCOIN_API_KEY,
  apiSecret: process.env.KUCOIN_API_SECRET,
  apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
};

const rest = new SpotClient(credentials);
const ws = new WebsocketClient(credentials);

let recoveryRunning = false;
let spotState;

async function recoverSpotState() {
  if (recoveryRunning) {
    return;
  }

  recoveryRunning = true;

  try {
    let balances;

    try {
      const response = await rest.getBalances({
        type: 'trade',
      });
      balances = response.data;
    } catch (error) {
      console.error('Balance recovery failed:', error);
      return;
    }

    let openOrders;

    try {
      const response = await rest.getHFActiveOrdersPaginated({
        symbol: 'BTC-USDT',
        pageNum: 1,
        pageSize: 100,
      });
      openOrders = response.data.items;
    } catch (error) {
      console.error('Open-order recovery failed:', error);
      return;
    }

    let fills;

    try {
      const response = await rest.getHFFilledOrders({
        symbol: 'BTC-USDT',
        limit: 100,
      });
      fills = response.data.items;
    } catch (error) {
      console.error('Fill recovery failed:', error);
      return;
    }

    spotState = {
      balances,
      openOrders,
      fills,
      recoveredAt: Date.now(),
    };

    console.log('Recovered Spot state:', spotState);
  } finally {
    recoveryRunning = false;
  }
}

ws.on('reconnected', async ({ wsKey }) => {
  if (wsKey !== WS_KEY_MAP.spotPrivateV1) {
    return;
  }

  await recoverSpotState();
});

ws.on('update', (update) => {
  console.log('Private Spot update:', update);
});

ws.on('exception', (error) => {
  console.error('WebSocket exception:', error);
});

try {
  ws.subscribe(
    ['/spotMarket/tradeOrdersV2', '/account/balance'],
    WS_KEY_MAP.spotPrivateV1,
  );
} catch (error) {
  console.error('Private Spot subscription failed:', error);
}

process.once('SIGINT', () => {
  ws.closeAll();
});

This is REST API hydration applied as scoped recovery. Reload only the state that may have changed on the affected connection.

For a wider recovery design, see Exchange State and Runtime Workflows.

Use the KuCoin WebSocket API

WebsocketAPIClient provides awaitable Spot, Margin, and Futures order commands. It opens and authenticates the selected connection, adds request IDs, matches responses, and resolves each command promise.

ProductRepresentative methods
SpotsubmitNewSpotOrder(), modifySpotOrder(), cancelSpotOrder()
Spot syncsubmitSyncSpotOrder(), cancelSyncSpotOrder()
MarginsubmitMarginOrder(), cancelMarginOrder()
FuturessubmitFuturesOrder(), cancelFuturesOrder(), submitMultipleFuturesOrders()

Successful responses include code, endpoint-specific data, inTime, outTime, and the SDK-added wsKey. Non-success responses reject the command promise.

Use connectWSAPI(wsKey) when an application wants to open and authenticate the connection before its first command. Automatic reauthentication after reconnect is enabled by default.

KuCoin WebSocket API order commands are live. Use the REST API test-order methods before enabling a WebSocket command in an account with funds.

Evaluate Unified Account and Pro APIs separately

KuCoin currently marks its Unified Account API as under active development and its Pro WebSocket API as beta. The official documentation says not to use these surfaces in production or live trading. Treat them as evaluation interfaces, not replacements for the Classic workflow in this guide.

See the official Unified Account introduction and Pro WebSocket introduction before testing them.

Make a public Unified REST API call

import { UnifiedAPIClient } from 'kucoin-api';

const client = new UnifiedAPIClient();

async function main() {
  try {
    const response = await client.getTickers({
      tradeType: 'SPOT',
      symbol: 'BTC-USDT',
    });
    console.log('Unified API ticker:', response.data);
  } catch (error) {
    console.error('Unified API ticker request failed:', error);
  }
}

main();

UnifiedAPIClient covers market data, accounts, transfers, orders, positions, funding, rate limits, and subaccounts. Endpoint availability depends on account eligibility and the current development phase.

Subscribe to a public Pro WebSocket

import { WebsocketClient, WS_KEY_MAP } from 'kucoin-api';

const ws = new WebsocketClient();

ws.on('response', (response) => {
  console.log('Pro WebSocket response:', response);
});

ws.on('update', (update) => {
  console.log('Pro ticker update:', update);
});

ws.on('exception', (error) => {
  console.error('Pro WebSocket exception:', error);
});

try {
  ws.subscribe(
    {
      topic: 'ticker',
      payload: {
        tradeType: 'SPOT',
        symbol: 'BTC-USDT',
      },
    },
    WS_KEY_MAP.spotPublicProV2,
  );
} catch (error) {
  console.error('Pro ticker subscription failed:', error);
}

process.once('SIGINT', () => {
  ws.closeAll();
});

Pro public Spot and Futures streams use spotPublicProV2 and futuresPublicProV2. Private Pro topics share privateProV2. Their topic and payload format differs from Classic topics.

Connect to live and regional APIs

KuCoin does not currently provide an active sandbox. The KuCoin sandbox suspension announcement remains the relevant environment notice. Use the Spot and Futures REST API test-order methods for safe request validation.

Live REST API hosts

Account or productREST API hostSDK routing
Global Spot and Marginhttps://api.kucoin.comDefault SpotClient
Global Futureshttps://api-futures.kucoin.comDefault FuturesClient
Global Brokerhttps://api-broker.kucoin.comDefault BrokerClient
KuCoin EU Spot and Marginhttps://api.kucoin.euapiRegion: 'EU'
KuCoin AUGlobal hosts with AU site selectionapiRegion: 'AU' adds the required site header

KuCoin EU currently supports Spot and Margin APIs but not Futures. Use credentials created for the same account region.

See the official KuCoin EU API documentation and KuCoin AU API documentation for current regional availability.

Set apiRegion instead of manually selecting a standard regional host:

import { SpotClient, WebsocketClient, WS_KEY_MAP } from 'kucoin-api';

const euSpot = new SpotClient({
  apiRegion: 'EU',
});

const auSpot = new SpotClient({
  apiRegion: 'AU',
});

const euWs = new WebsocketClient({
  apiRegion: 'EU',
});

euWs.on('open', ({ wsKey }) => {
  console.log('EU Classic WebSocket opened:', wsKey);
});

euWs.on('exception', (error) => {
  console.error('EU Classic WebSocket exception:', error);
});

async function main() {
  try {
    const response = await euSpot.getServerTime();
    console.log('EU API server time:', response.data);
  } catch (error) {
    console.error('EU API server-time request failed:', error);
  }

  try {
    const response = await auSpot.getSymbols();
    console.log('AU Spot symbols:', response.data);
  } catch (error) {
    console.error('AU Spot symbols request failed:', error);
  }

  try {
    await euWs.connect(WS_KEY_MAP.spotPublicV1);
    console.log('EU Classic WebSocket connection is ready.');
  } catch (error) {
    console.error('EU Classic WebSocket connection failed:', error);
  }
}

process.once('SIGINT', () => {
  euWs.closeAll();
});

main();

Classic WebSocket hosts are obtained from KuCoin's connection-token response. The SDK uses the selected region for that request. Do not hardcode a regional WebSocket URL that is not supplied by the official documentation and supported by the installed SDK version.

After connecting, subscribe only to symbols and topics available to the selected account region.

The optional baseUrl setting overrides normal region routing. Reserve it for a documented host that the account is allowed to use.

Use a proxy with the REST API and WebSockets

kucoin-api accepts standard Node.js agents. Classic WebSockets need proxy configuration in two places:

  • requestOptions carries the connection-token REST API request through the proxy.
  • wsOptions.agent carries the WebSocket connection through the proxy.

REST API clients accept Axios network options as their second constructor argument.

See Using proxies with Siebly SDKs for deployment and troubleshooting guidance.

HTTP and HTTPS proxy

Install the proxy agent:

npm install https-proxy-agent

Set KUCOIN_PROXY_URL to an http:// or https:// proxy URL:

import { HttpsProxyAgent } from 'https-proxy-agent';
import { SpotClient, WebsocketClient, WS_KEY_MAP } from 'kucoin-api';

async function main() {
  const proxyUrl = process.env.KUCOIN_PROXY_URL;

  if (!proxyUrl) {
    console.error('Set KUCOIN_PROXY_URL.');
    return;
  }

  const agent = new HttpsProxyAgent(proxyUrl);

  const rest = new SpotClient(
    {},
    {
      httpsAgent: agent,
      proxy: false,
    },
  );

  const ws = new WebsocketClient({
    requestOptions: {
      httpsAgent: agent,
      proxy: false,
    },
    wsOptions: {
      agent,
    },
  });

  ws.on('open', ({ wsKey }) => {
    console.log('WebSocket connected through proxy:', wsKey);
  });

  ws.on('response', (response) => {
    console.log('Subscription response:', response);
  });

  ws.on('update', (update) => {
    console.log('Ticker update through proxy:', update);
    ws.closeAll();
  });

  ws.on('exception', () => {
    console.error('WebSocket proxy connection failed.');
  });

  try {
    const response = await rest.getServerTime();
    console.log('Server time through proxy:', response.data);
  } catch {
    console.error('REST API proxy request failed.');
  }

  try {
    ws.subscribe('/market/ticker:BTC-USDT', WS_KEY_MAP.spotPublicV1);
  } catch {
    console.error('WebSocket proxy subscription failed.');
  }

  process.once('SIGINT', () => {
    ws.closeAll();
  });
}

main();

For an authenticated HTTP or HTTPS proxy, include the username and password in KUCOIN_PROXY_URL. Percent-encode reserved characters in each credential component.

SOCKS5 proxy

Install the SOCKS agent:

npm install socks-proxy-agent

Set KUCOIN_SOCKS_PROXY_URL to a socks5:// URL:

import { SocksProxyAgent } from 'socks-proxy-agent';
import { SpotClient, WebsocketClient, WS_KEY_MAP } from 'kucoin-api';

async function main() {
  const proxyUrl = process.env.KUCOIN_SOCKS_PROXY_URL;

  if (!proxyUrl) {
    console.error('Set KUCOIN_SOCKS_PROXY_URL.');
    return;
  }

  const agent = new SocksProxyAgent(proxyUrl);

  const rest = new SpotClient(
    {},
    {
      httpsAgent: agent,
      proxy: false,
    },
  );

  const ws = new WebsocketClient({
    requestOptions: {
      httpsAgent: agent,
      proxy: false,
    },
    wsOptions: {
      agent,
    },
  });

  ws.on('open', ({ wsKey }) => {
    console.log('WebSocket connected through SOCKS5:', wsKey);
  });

  ws.on('response', (response) => {
    console.log('Subscription response:', response);
  });

  ws.on('update', (update) => {
    console.log('Ticker update through SOCKS5:', update);
    ws.closeAll();
  });

  ws.on('exception', () => {
    console.error('SOCKS5 WebSocket connection failed.');
  });

  try {
    const response = await rest.getServerTime();
    console.log('Server time through SOCKS5:', response.data);
  } catch {
    console.error('SOCKS5 REST API request failed.');
  }

  try {
    ws.subscribe('/market/ticker:BTC-USDT', WS_KEY_MAP.spotPublicV1);
  } catch {
    console.error('SOCKS5 WebSocket subscription failed.');
  }

  process.once('SIGINT', () => {
    ws.closeAll();
  });
}

main();

Private REST API, stream, and WebSocket API traffic

Use the same agent for private REST API calls, connection-token requests, private stream connections, and WebSocket API connections:

import { HttpsProxyAgent } from 'https-proxy-agent';
import {
  SpotClient,
  WebsocketAPIClient,
  WebsocketClient,
  WS_KEY_MAP,
} from 'kucoin-api';

async function main() {
  const proxyUrl = process.env.KUCOIN_PROXY_URL;

  if (!proxyUrl) {
    console.error('Set KUCOIN_PROXY_URL.');
    return;
  }

  if (
    !process.env.KUCOIN_API_KEY ||
    !process.env.KUCOIN_API_SECRET ||
    !process.env.KUCOIN_API_PASSPHRASE
  ) {
    console.error(
      'Set KUCOIN_API_KEY, KUCOIN_API_SECRET, and KUCOIN_API_PASSPHRASE.',
    );
    return;
  }

  const agent = new HttpsProxyAgent(proxyUrl);
  const credentials = {
    apiKey: process.env.KUCOIN_API_KEY,
    apiSecret: process.env.KUCOIN_API_SECRET,
    apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
  };

  const rest = new SpotClient(credentials, {
    httpsAgent: agent,
    proxy: false,
  });

  const streams = new WebsocketClient({
    ...credentials,
    requestOptions: {
      httpsAgent: agent,
      proxy: false,
    },
    wsOptions: {
      agent,
    },
  });

  const wsApi = new WebsocketAPIClient({
    ...credentials,
    wsOptions: {
      agent,
    },
  });

  streams.on('update', (update) => {
    console.log('Private update through proxy:', update);
  });

  streams.on('exception', () => {
    console.error('Private stream proxy connection failed.');
  });

  try {
    const response = await rest.getBalances({
      type: 'trade',
    });
    console.log('Spot balances through proxy:', response.data);
  } catch {
    console.error('Private REST API proxy request failed.');
  }

  try {
    streams.subscribe('/account/balance', WS_KEY_MAP.spotPrivateV1);
  } catch {
    console.error('Private stream subscription failed.');
  }

  try {
    await wsApi.connectWSAPI(WS_KEY_MAP.wsApiSpotV1);
    console.log('WebSocket API authenticated through proxy.');
  } catch {
    console.error('WebSocket API proxy connection failed.');
  }

  process.once('SIGINT', () => {
    streams.closeAll();
    wsApi.getWSClient().closeAll();
  });
}

main();

The proxy's egress IP is the address KuCoin sees. Add it to the API key whitelist when a whitelist is enabled. Use a stable proxy endpoint and monitor its availability and latency.

A proxy changes the network path, not request signing, API permissions, account eligibility, or regional availability. Treat HTTP 407 responses, TLS failures, token-request failures, and repeated reconnects as network faults.

Production checklist

Keep request time accurate

KuCoin rejects private requests when the client timestamp differs from server time by more than the allowed window. Keep the host clock synchronized with NTP. Use getServerTime() for diagnosis, then fix the system clock instead of applying an unbounded application offset.

Respect rate limits

Rate limits vary by product, permission, endpoint weight, account level, region, and connection type. Read the current KuCoin rate-limit documentation and monitor returned error details.

Retry temporary network failures and rate-limit responses with bounded exponential backoff and jitter. Do not blindly retry an order after an ambiguous timeout. Query by clientOid or reconcile current order state first.

Use client-generated order IDs

Set a unique clientOid on each application-owned order. Store it before sending the request. This gives retries, restarts, REST API queries, and stream updates a common identifier.

Apply product metadata

Before placing a Spot order, check enableTrading, minimum and maximum sizes, minFunds, and price and size increments.

Before placing a Futures order, check contract status, multiplier, lotSize, tickSize, maxOrderQty, maxLeverage, margin mode support, and position mode.

Use a decimal arithmetic library for production sizing and rounding when native floating-point arithmetic could change an order amount.

Confirm final state

A REST API response or WebSocket API response can arrive before later matching, fills, cancellations, or amendments. Record the command response, then confirm final state through private streams and a REST API query.

After a reconnect, restore the affected exchange state before resuming state-dependent actions.

Plan for WebSocket renewal

Classic connection tokens are valid for 24 hours, and a connection is expected to end after that period. Treat reconnects as normal. The SDK reconnects and restores subscriptions, while the application reloads any private state that may have changed during the gap.

Use dead-man-switch protection where appropriate

Spot HF endpoints include cancelHFOrderAutoSetting() and cancelHFOrderAutoSettingQuery(). A dead-man switch can reduce the time stale orders remain open after an application or network failure. Configure and monitor it as part of the trading system, not as a replacement for recovery.

Scope credentials and network access

  • Grant General permission to read-only services.
  • Add Spot, Margin, Futures, or Earn permission only where needed.
  • Do not grant Withdrawal permission to trading services.
  • Use IP restrictions when egress addresses are stable.
  • Keep region-specific credentials with the matching account region.
  • Monitor proxy availability and egress IP changes.

Keep developing APIs out of production

Do not route production trading through Unified Account or Pro WebSocket APIs while the official KuCoin documentation marks them as developing or beta.

Shut down connections

Call closeAll() on each WebSocket client when the process is ending. An unsubscribe request is unnecessary when the connection is about to close.

FAQ

Does kucoin-api work with plain JavaScript?

Yes. Every example in this guide is JavaScript, and the npm package supports both CommonJS and ESM projects.

Which REST API client should I use?

Use SpotClient for Classic Spot, Margin, funding, Earn, and Convert endpoints. Use FuturesClient for Classic Futures. Use BrokerClient for broker operations. Treat UnifiedAPIClient as an evaluation surface while the official API remains under development.

Why does every successful response contain code and data?

That is KuCoin's REST API response envelope. code: '200000' indicates success, and the endpoint-specific result is under data. The SDK throws non-success business responses.

What is the API passphrase?

It is the passphrase chosen when creating the API key. It is not the KuCoin account password. The key, secret, and passphrase are all required for signed requests.

Why do current Spot methods contain HF?

They map to KuCoin's current high-frequency Spot API paths. Methods such as submitHFOrder() and getHFActiveOrdersPaginated() are the preferred current Spot methods, not special low-level SDK modes.

Should I use trade or trade_hf?

Most current users use trade. Some older high-frequency accounts use trade_hf. getUserType() is a compatibility check for those older accounts.

Does KuCoin have a TestNet or sandbox?

KuCoin suspended its sandbox. Use submitHFOrderTest() and submitNewOrderTest() to validate Spot and Futures order requests without entering the matching engine.

Can a test order be queried or cancelled?

No. A REST API test order never enters the matching engine. Its returned order ID is part of the validation response only.

Are WebSocket API order commands test orders?

No. KuCoin's WebSocket API order commands are live. Keep them behind an explicit application-level opt-in and validate the equivalent request through the REST API test-order method first.

Does a successful WebSocket API response mean the order filled?

No. It confirms the command response. Confirm matching, fills, and final order state through private streams and a REST API query.

What is the difference between Classic and Pro WebSockets?

Classic connections use V1 topics such as /market/ticker:BTC-USDT. Pro connections use structured V2 topics and payloads. KuCoin currently marks Pro APIs as beta, so this guide uses Classic WebSockets for production-oriented examples.

Which WS_KEY_MAP value should I use?

Choose the key for the exact product and access level. Spot and Futures, public and private, Classic and Pro, and WebSocket API commands all use distinct keys.

Why is a Futures size not a BTC amount?

Futures size is a contract count. Read multiplier and lotSize from contract metadata to calculate the underlying exposure.

Why did a Futures order fail after switching position mode?

One-way mode uses positionSide: 'BOTH'. Hedge mode separates LONG and SHORT. Query getPositionMode() and keep the order side and position side consistent.

How do EU and AU accounts use the SDK?

Set apiRegion: 'EU' or apiRegion: 'AU'. EU uses its regional Spot and Margin REST API host. AU uses the required site selection while retaining supported hosts. Use credentials from the same account region.

Can REST API and WebSocket traffic use the same proxy?

Yes. Pass the agent to the REST API client's network options, the Classic WebSocket token request through requestOptions, and the socket through wsOptions.agent.

Does a proxy change signing or account eligibility?

No. The SDK signs the same requests through the proxy. API permissions, region, account eligibility, and product availability still apply.

What causes timestamp or signature errors?

Common causes are a drifting system clock, the wrong API secret or passphrase, an incorrect API key version, credentials from another region, or a request reaching the wrong host. Verify these values without logging secrets.

What should happen after a WebSocket reconnect?

Allow the SDK to restore cached subscriptions, then reload affected balances, open orders, fills, and positions from the REST API before trusting the rebuilt state.

Next steps

Subscribe on Substack

Complete the Substack form below to join our newsletter. Substack handles all subscriber data directly.