Blog
WebSocketsTrading systemsTypeScriptNode.jsJavaScript

KuCoin Node.js SDK: A Guide to Modern Exchange Integration

Build a production-ready KuCoin integration with a modern Kucoin node sdk. Eliminate auth boilerplate and leverage awaitable WebSockets in your Node.js app.

Siebly.io10 min readMarkdown

Overview

If you have integrated KuCoin the hard way, you already know the pain: HMAC-SHA256 request signing, a passphrase that is easy to get wrong, and official Node.js wrappers that no longer move. Building a custom Kucoin node sdk from scratch means you own timestamps, headers, reconnects, and every API change after that.

This guide shows how to use kucoin-api, a TypeScript-first Node.js SDK, as the implementation layer. You will wire REST clients, subscribe to public and private WebSockets, and place orders over the WebSocket API with async/await. Official KuCoin docs stay the source of truth for endpoints. Rate limits and throttling stay in your application. We will also cover Classic REST plus the Unified Trading Account (UTA / Pro) API surface.

Key Takeaways

  • The official KuCoin Node.js and Futures SDKs were archived on March 4, 2025. A maintained Kucoin node sdk avoids sitting on a read-only repo.
  • Pass your API key, secret, and passphrase into the client. The SDK signs REST and WebSocket requests with HMAC-SHA256. You do not hand-roll the pre-hash string.
  • Use WebsocketAPIClient when you want awaitable order calls over a persistent WebSocket, instead of matching request IDs yourself.
  • The SDK does not throttle for you. Rate limits depend on VIP level and whether you hit UTA or Classic endpoints.
  • Heartbeats, reconnect, and topic resubscribe are built in. After a drop, still reconcile your local order and balance state.

The Current State of KuCoin Node.js SDKs

On March 4, 2025, KuCoin archived kucoin-node-sdk and kucoin-futures-node-sdk. Both repos are read-only. KuCoin pointed people at a multi-language Universal SDK. That is a real shift, and it is also a red flag if your production stack still imports those archived packages: no security patches, no dependency updates, no coverage for newer API families.

You can keep a raw REST client in-house, or you can use a maintained Kucoin node sdk. The first option means you own every signing bug and every endpoint rename.

Why Official SDK Deprecation Matters

Archived code and a live exchange drift apart. As of August 2026, KuCoin still ships Classic REST (spot on api.kucoin.com, futures on api-futures.kucoin.com) and a Unified Trading Account API under /api/ua/v1. In June 2026 they moved the Pro API onto that UTA surface and said UTA would be the focus going forward. Archived Node wrappers do not track that split.

When the official tool is frozen, HMAC-SHA256, passphrase headers, and VIP rate-limit changes all land on your team. That is a bad place to be during a volatility spike.

Siebly as the Preferred Implementation Layer

kucoin-api is a TypeScript-first SDK. Most request and response shapes are typed. Official docs remain the source of truth for what an endpoint accepts.

It is not one mega-client. REST is split on purpose:

  • SpotClient - spot and margin
  • FuturesClient - futures
  • BrokerClient - broker and sub-accounts
  • UnifiedAPIClient - UTA / Pro endpoints across spot, futures, and margin (tradeType selects the market)

WebSockets go through WebsocketClient (streams) and WebsocketAPIClient (awaitable trading over WS).

The SDK handles networking and signing. It does not auto-throttle. You implement rate-limit logic for your VIP level and endpoint family.

Authentication and Request Signing for KuCoin

KuCoin private calls need three credentials: API key, API secret, and API passphrase. That passphrase is not your account password. It is the string you set when you created the key.

Signing is HMAC-SHA256. The pre-hash string is:

timestamp + HTTP method + /endpoint + body-or-query

The passphrase is not part of that pre-hash. For API key version 2 (the SDK default), the passphrase is HMAC-SHA256 signed on its own and sent as KC-API-PASSPHRASE. The request signature goes in KC-API-SIGN. Manual implementations usually fail on JSON body serialisation, query string encoding, or clock skew.

Pass the three values into the constructor. The client signs REST and private WebSocket traffic from there.

Imported example

JavaScript
const { SpotClient } = require("kucoin-api");

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

Same shape for FuturesClient and UnifiedAPIClient. Public market data does not need keys. Create an empty client if you only read tickers and books.

The SDK does not rate-limit you. Keep that in your app.

Managing API Credentials Safely

Keep keys in environment variables. Never commit them. Use least privilege: trading automation should not have withdrawal permission. That lines up with broader industry talk, including SEC Proposed Crypto Regulations, on how digital assets and access credentials should be safeguarded. A dedicated KuCoin JavaScript SDK at least keeps signing in one place instead of copy-pasted header code.

Handling Timestamps and Clock Skew

KuCoin rejects signed requests when your KC-API-TIMESTAMP is more than 5 seconds off server time (error 400002). The SDK uses Date.now() unless you pass customTimestampFn. It does not generate nonces. There is no nonce in this auth scheme.

Sync the host with NTP. If you still see skew, call getServerTime() (GET /api/v1/timestamp) and feed a corrected clock into customTimestampFn. SpotClient also exposes fetchLatencySummary() if you want a quick local-vs-server check. Do not assume the client silently rewrites every timestamp for you.

Transitioning to Awaitable WebSockets for KuCoin

Market data is fine as event listeners (update, reconnect, reconnected). Order placement over WebSocket is not. Matching request IDs across the process is busywork.

kucoin-api exposes two WS API styles:

  • WebsocketClient.sendWSAPIRequest() - promise-wrapped, still close to the raw command
  • WebsocketAPIClient - one method per endpoint, REST-like, connection kept alive for you

That is the awaitable pattern. Same linear await as REST, without opening a new HTTP session per order.

A persistent socket also matters if you care about operational traceability. Guidance such as the FinCEN Virtual Currency Guidance is about the businesses around the exchange, not about this npm package, but the engineering point stands: keep connectivity boring and logs complete. Heartbeats and reconnect are in the client. Rate limits are still yours.

Awaitable Order Placement via WebSocket

WebsocketAPIClient is the straightforward path. This matches the SDK example in examples/WebSockets/WS-API/ws-api-client.ts:

Imported example

JavaScript
const { WebsocketAPIClient } = require("kucoin-api");

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

async function placeSpotLimit() {
  const response = await wsClient.submitNewSpotOrder({
side: "buy",
symbol: "BTC-USDT",
type: "limit",
price: "20000",
size: "0.0001",
  });
  console.log(response);
}

async function placeFuturesLimit() {
  const response = await wsClient.submitFuturesOrder({
clientOid: "futures-test-" + Date.now(),
side: "buy",
symbol: "XBTUSDTM",
marginMode: "CROSS",
type: "limit",
price: "1000",
qty: "0.01",
leverage: 10,
positionSide: "LONG",
  });
  console.log(response);
}

Use prices and sizes that cannot fill if you are only testing the round trip. submitSyncSpotOrder waits for the matching-engine ack. Futures batch helpers exist too (submitMultipleFuturesOrders, cancelMultipleFuturesOrders).

Managing WebSocket Subscriptions

Public streams do not need keys. Private account streams do. The client authenticates when you pass credentials.

V1 topics still work (spotPublicV1, futuresPublicV1, spotPrivateV1). V2 / Pro / UTA topics use keys such as spotPublicProV2, futuresPublicProV2, and privateProV2. Private V2 topics share one connection.

Public ticker example from examples/WebSockets/ws-public-spot-v1.ts:

Imported example

JavaScript
const { WebsocketClient } = require("kucoin-api");

const ws = new WebsocketClient();

ws.on("update", (data) => {
  console.log("data received:", JSON.stringify(data));
});

ws.on("reconnect", (data) => {
  console.log("reconnect:", data);
});

ws.on("reconnected", (data) => {
  console.log("reconnected:", data);
});

ws.on("exception", (data) => {
  console.error("exception:", data);
});

ws.subscribe("/market/ticker:BTC-USDT,ETH-USDT", "spotPublicV1");

Private UTA / Pro orders, from examples/WebSockets/ws-private-pro-v2.ts:

Imported example

JavaScript
const { WebsocketClient, WS_KEY_MAP } = require("kucoin-api");

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

ws.on("update", (data) => {
  console.log("private update:", JSON.stringify(data));
});

ws.subscribe(
  {
topic: "orderAll",
payload: { tradeType: "UNIFIED" },
  },
  WS_KEY_MAP.privateProV2,
);

ws.subscribe(
  {
topic: "positionAll",
payload: { tradeType: "FUTURES" },
  },
  WS_KEY_MAP.privateProV2,
);

Reconnect resubscribes stored topics automatically. After reconnected, refresh orders and balances with REST so your cache is not stale. More stream detail is in the KuCoin JavaScript SDK tutorial.

Engineering Reliable Market Data Pipelines

Keep ingestion off the hot path of your strategy code. Typed responses help, especially on order book deltas. The SDK types most payloads. It does not magically protect you from KuCoin changing a field.

Respect rate limits in your process. kucoin-api will not queue or back off for you. UTA limits are per second and scale with VIP. Classic spot, futures, and public pools use a 30-second window. 429s and IP bans are on you if you ignore that.

Building a Data Collector in Node.js

Separate the socket reader from analysis. Use REST for snapshots and history, WebSockets for the live tape.

Spot public REST, from examples/Rest/rest-spot-public.ts:

Imported example

JavaScript
const { SpotClient } = require("kucoin-api");

const client = new SpotClient();

async function collectSpot() {
  const symbols = await client.getSymbols();
  const ticker = await client.getTicker({ symbol: "BTC-USDT" });
  const klines = await client.getKlines({
symbol: "BTC-USDT",
type: "1day",
  });
  console.log({ symbols, ticker, klines });
}

collectSpot().catch(console.error);

UTA market data, from examples/kucoin-UNIFIED-examples-nodejs.md:

Imported example

JavaScript
const { UnifiedAPIClient } = require("kucoin-api");

const unifiedClient = new UnifiedAPIClient();

async function collectUnified() {
  const spotTickers = await unifiedClient.getTickers({ tradeType: "SPOT" });
  const futuresTicker = await unifiedClient.getTickers({
tradeType: "FUTURES",
symbol: "XBTUSDTM",
  });
  const klines = await unifiedClient.getKlines({
tradeType: "SPOT",
symbol: "BTC-USDT",
interval: "1hour",
startAt: Date.now() - 24 * 60 * 60 * 1000,
endAt: Date.now(),
  });
  console.log({ spotTickers, futuresTicker, klines });
}

collectUnified().catch(console.error);

On 429, back off. A token bucket or a small queue across workers is enough. Install kucoin-api and point your collector at the public methods first.

Managing Order and Account State

Do not poll REST for every fill. Snapshot with REST, then apply private WS updates.

Imported example

JavaScript
const { UnifiedAPIClient } = require("kucoin-api");

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

async function snapshot() {
  const account = await unifiedClient.getAccount();
  const open = await unifiedClient.getOpenOrderList(
{ tradeType: "SPOT", symbol: "BTC-USDT", pageSize: 50 },
"unified",
  );
  return { account, open };
}

Patterns for that hybrid cache are in Siebly research on order flow. Pair them with the KuCoin JavaScript SDK.

Implementing KuCoin Integrations with Siebly kucoin-api

Install the package:

Imported example

Shell
npm install kucoin-api

Yarn is yarn add kucoin-api. The library targets Node.js and TypeScript. ESM and CommonJS both work.

Pick the client that matches the API family you actually call. Classic spot orders go through SpotClient (HF helpers such as submitHFOrder). Futures go through FuturesClient. UTA / Pro trading goes through UnifiedAPIClient, with accountMode 'unified' or 'classic'. Do not assume one constructor covers every KuCoin URL.

Quickstart with Siebly kucoin-api

Public ticker plus a UTA limit order (from the unified examples). The second argument to placeOrder is the account mode. Default is 'unified'.

Imported example

JavaScript
const { UnifiedAPIClient } = require("kucoin-api");

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

async function main() {
  const ticker = await unifiedClient.getTickers({
tradeType: "SPOT",
symbol: "BTC-USDT",
  });
  console.log(ticker);

  const order = await unifiedClient.placeOrder(
{
tradeType: "SPOT",
clientOid: "my-client-oid-" + Date.now(),
symbol: "BTC-USDT",
side: "BUY",
orderType: "LIMIT",
size: "0.001",
sizeUnit: "BASECCY",
price: "40000",
timeInForce: "GTC",
},
"unified",
  );
  console.log(order);
}

main().catch(console.error);

Classic spot HF order, from examples/Rest/rest-spot-private-trade.ts:

Imported example

JavaScript
const { SpotClient } = require("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 placeHfMarket() {
  const result = await client.submitHFOrder({
clientOid: client.generateNewOrderID(),
side: "buy",
type: "market",
symbol: "BTC-USDT",
size: "0.00001",
  });
  console.log(result);
}

placeHfMarket().catch(console.error);

generateNewOrderID() returns a nanoid. Use it for clientOid instead of rolling your own uniqueness. Method lists live in the Siebly KuCoin SDK guide.

Testing and Safety Boundaries

KuCoin's old sandbox (openapi-sandbox.kucoin.com) is offline. Official docs say the independent sandbox stopped maintenance. kucoin-api has no working testnet base URL, so do not look for a testnet: true switch that points at a real KuCoin sandbox.

What you can do:

  • Spot HF mock: submitHFOrderTest (POST /api/v1/hf/orders/test)
  • Older mock: submitOrderTest (deprecated; prefer the HF test method)
  • Trade tiny size on live
  • Use paper trading workflows for architecture checks

Cap order size in your own code. Disable withdrawals on bot keys. Validate signing and WS subscribe on public data before you send a live order.

Advancing Your KuCoin Integration Architecture

Archived official wrappers and homemade signing are the two usual failure modes. A maintained Kucoin node sdk gets you typed REST clients, a unified WebSocket consumer, and awaitable WS API calls.

kucoin-api is TypeScript-first and ships ESM plus CommonJS. Signing and socket frame handling are in the library. Rate limits, order-size caps, and state reconciliation after reconnect stay in your process.

Ready to wire it up? Explore the Siebly KuCoin JavaScript SDK. Start with public REST, then private WS, then one guarded order call.

Frequently Asked Questions

Is the official KuCoin Node.js SDK still supported?

No. kucoin-node-sdk and kucoin-futures-node-sdk were archived on March 4, 2025. The repos are read-only. KuCoin recommends their Universal SDK. If you want a maintained TypeScript Node client with dedicated spot, futures, broker, UTA, and WebSocket classes, use kucoin-api from Siebly.io.

How do I handle KuCoin API rate limits in Node.js?

Limits depend on product and VIP level. On the Unified Account pool, VIP0 is 300 requests per second. Classic spot (including margin) for VIP0 is 4000 per 30 seconds. Futures, public, and other Classic pools have their own 30-second quotas. UTA quota can be split across master and sub-accounts. kucoin-api does not throttle. Put a token bucket or a queue in front of the client and back off on 429.

Can I use the Siebly KuCoin SDK with TypeScript?

Yes. The package is written in TypeScript. Request objects and most responses have declarations, so the editor can complete method names and flag bad params before runtime.

Does the KuCoin API require a passphrase for authentication?

Yes. Key, secret, and passphrase are all required for private calls. The passphrase is signed and sent as KC-API-PASSPHRASE. It is not concatenated into the request pre-hash. The pre-hash is timestamp, method, path, and body. Pass all three constructor fields: apiKey, apiSecret, apiPassphrase.

What is the difference between KuCoin Spot and Futures APIs?

Auth is the same three credentials. In this SDK, use SpotClient and FuturesClient for those Classic APIs. UnifiedAPIClient talks to /api/ua/v1 and selects the market with tradeType: 'SPOT' | 'FUTURES'. WebsocketClient covers both markets; you pass a wsKey so the right socket is used.

How do I manage WebSocket reconnections for KuCoin?

The client heartbeats, reconnects, re-auths private sockets, and resubscribes topics it already stored. Listen for reconnect and reconnected. After reconnected, do a REST snapshot of orders and balances. You do not need to call subscribe again for topics that were still in the store. Call unsubscribe if you want a topic gone after the next drop.

Is there a testnet or sandbox for KuCoin API development?

Not a live one you should rely on. KuCoin took the independent sandbox offline. This SDK does not point at a working testnet URL. Use submitHFOrderTest for spot HF dry-runs, tiny live orders, or paper-trading flows. Never assume a sandbox flag will save you from hitting production.

How do I sign KuCoin API requests correctly?

Build timestamp + method + /endpoint + body (query string with ? for GET/DELETE). HMAC-SHA256 with the secret, Base64-encode, send as KC-API-SIGN. Send the key, version, timestamp, and signed passphrase in the other KC-API-* headers. kucoin-api does this on every private REST call. You should not reimplement it unless you are debugging a signature mismatch.

Disclaimer

*Technical and legal disclaimer: Siebly.io provides software development tools, SDKs, documentation, and educational engineering content for crypto exchange API integrations. This content is for software engineering education only and is not financial, investment, legal, tax, accounting, compliance, or trading advice.

Nothing in this article is a recommendation, invitation, or inducement to buy, sell, hold, trade, long, short, or allocate to any cryptoasset, exchange product, strategy, bot, or automated workflow. Examples, code patterns, simulations, backtests, and architecture diagrams are illustrative only and must not be treated as trading signals, investment recommendations, or evidence of future performance.

Cryptoasset markets are high risk and volatile. If you choose to build or operate exchange-connected software, you are responsible for your own legal, regulatory, tax, security, exchange-account, API-key, and risk-management obligations. Use public data, testnet, demo, dry-run, or paper-trading workflows before any live execution. Keep API keys server-side, use least-privilege permissions, and never enable withdrawals for automation keys unless you fully understand and accept the risks.

Siebly.io is not an exchange, custodian, investment adviser, trading-signal provider, or managed trading service. Official exchange documentation remains the source of truth for exchange-specific rules, API behavior, and terms of use. Use of Siebly.io content and software is also subject to the Siebly.io terms and conditions.*

Related articles

Continue from here

Related Siebly resources

All articles

Subscribe on Substack

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