Blog
WebSocketsTrading systemsTypeScriptNode.jsJavaScript

KuCoin Spot API TypeScript SDK: A Practical Integration Guide

Integrate the KuCoin Spot API TypeScript SDK in Node.js. Streamline authentication, signing, and awaitable WebSockets while keeping full rate limit control.

Siebly.io7 min readMarkdown

Overview

The KuCoin Spot API TypeScript SDK is the npm package kucoin-api. It sits in front of KuCoin’s REST and WebSocket APIs and takes care of request signing, timestamps, and TypeScript types. Your application still decides when to send a request, what to do when it fails, and how to pace calls so you stay inside KuCoin’s rate limits.

Install it with npm install kucoin-api. The package publishes both ESM and CommonJS builds, plus TypeScript declarations. Setup and the current export list are on the KuCoin JavaScript SDK quickstart. Endpoint behavior still comes from KuCoin’s API docs.

This guide is about spot. The same package also ships FuturesClient, BrokerClient, and UnifiedAPIClient if you need those later.

Key Takeaways

  • Package name is kucoin-api. Spot work goes through SpotClient. Public market calls need no keys.
  • Private calls need three values: apiKey, apiSecret, and apiPassphrase. The passphrase is the one you chose when you created the API key. It is not your account password.
  • The client signs requests and attaches the timestamp. It does not retry a failed REST call, and it does not throttle for you.
  • Streams use WebsocketClient. It reconnects and resubscribes after a drop. You still apply the messages to your own state.
  • Promise-style WebSocket trading uses WebsocketAPIClient. That client is specific to kucoin-api. Other Siebly exchange packages do not all work this way.

What you get from kucoin-api

A KuCoin request is more than a URL. Private calls need an HMAC signature, a millisecond timestamp (KC-API-TIMESTAMP), a signed passphrase, and a body shaped the way that endpoint expects. SpotClient builds that for you. If you pass a custom customTimestampFn, the client uses that clock instead of Date.now().

Most request and response objects are typed. When KuCoin changes a field, the types in the package are only as current as the version you installed, so check the release you are on against KuCoin’s docs before you depend on a field.

The other clients in the same package:

ClientUse it for
SpotClientSpot and margin REST
FuturesClientFutures REST
BrokerClientBroker and sub-account REST
UnifiedAPIClientKuCoin’s unified (Pro) REST endpoints
WebsocketClientPublic and private streams, spot and futures
WebsocketAPIClientTrading commands over a WebSocket, returned as a promise

Public market data

Public endpoints do not need credentials. new SpotClient() with no arguments is enough. This matches examples/Rest/rest-spot-public.ts in the repo.

Imported example

JavaScript
import { SpotClient } from "kucoin-api";

const client = new SpotClient();

const symbols = await client.getSymbols();
console.log("symbols:", symbols);

const ticker = await client.getTicker({ symbol: "BTC-USDT" });
console.log("ticker:", ticker);

const klines = await client.getKlines({
  symbol: "BTC-USDT",
  type: "1day",
});
console.log(klines);

getTicker reads the level-1 book for one symbol (api/v1/market/orderbook/level1). getTickers() returns every symbol. These calls hit KuCoin’s live market-data API. The SDK does not ship a sandbox host.

Private calls and credentials

Load the key, secret, and passphrase from the environment. If you set any one of the three and leave another empty, the constructor throws. Leave all three unset and you get a public-only client.

Imported example

JavaScript
import { SpotClient } from "kucoin-api";

const client = new SpotClient({
  apiKey: process.env.API_KEY,
  apiSecret: process.env.API_SECRET,
  apiPassphrase: process.env.API_PASSPHRASE,
});

const balances = await client.getBalances();
console.log(balances);

getBalances() calls GET api/v1/accounts. Keep the key off disk in source files, and turn withdrawal permission off for any key a bot uses. Errors thrown by the REST client omit the key, secret, and passphrase from the request options attached to the error, so a log of that object will not print them. Do not log process.env next to it.

A spot limit order on REST follows examples/kucoin-SPOT-examples-nodejs.md. generateNewOrderID() fills clientOid. This sends a live order if the key can trade. The price below is the sample from that file, on ETH-BTC. Use your own price.

Imported example

JavaScript
const order = await client.submitOrder({
  clientOid: client.generateNewOrderID(),
  side: "buy",
  symbol: "ETH-BTC",
  type: "limit",
  price: "0.03",
  size: "0.5",
  timeInForce: "GTC",
});

What stays in your application

Signing and types are the SDK’s job. Scheduling is yours.

Responsibilitykucoin-apiYour application
Authentication and signingSigns private REST calls with key, secret, and passphrase.Store the three values and choose the key’s permissions.
TimestampsSends KC-API-TIMESTAMP. Override with customTimestampFn if your clock drifts.Keep the host clock close to KuCoin’s.
Request shapesTypeScript types for most calls.Match the fields to the current KuCoin docs.
REST retriesA failed call is thrown once.Decide if that call is safe to send again.
Rate limitsNo limiter and no automatic backoff.Slow down on KuCoin’s rate-limit responses.

The same rate-limit split holds for the other Siebly exchange packages in this set (binance, bitget-api, bitmart-api, bybit-api, coinbase-api, gateio-api, @siebly/htx-api, @siebly/kraken-api, okx-api). None of them queue or throttle REST traffic for you.

An order create is not safe to fire again just because the HTTP call threw. You may have created the order and lost the response. Read the order back, or send a clientOid you can look up, before you submit a second one.

WebSocket streams

WebsocketClient is for subscriptions. Public spot data needs no keys. The client opens the connection, sends heartbeats, and if the socket drops it reconnects and resubscribes. You still own the book or ticker you build from those messages. A reconnect can skip updates, so treat the stream as a feed you have to reconcile, not as a database.

The snippet below follows examples/WebSockets/ws-public-spot-pro-v2.ts. spotPublicProV2 is the WsKey for KuCoin’s Pro public spot socket. The tradeType inside the payload has to match that connection.

Imported example

JavaScript
import { WebsocketClient } from "kucoin-api";

const client = new WebsocketClient();

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

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

client.subscribe(
  [
{
topic: "ticker",
payload: {
tradeType: "SPOT",
symbol: "BTC-USDT",
},
},
{
topic: "trade",
payload: {
tradeType: "SPOT",
symbol: "BTC-USDT",
},
},
  ],
  "spotPublicProV2",
);

Private account streams use the same client with apiKey, apiSecret, and apiPassphrase in the constructor. The client authenticates that connection for you.

Placing a spot order over the WebSocket API

KuCoin also accepts trading commands on a WebSocket. WebsocketAPIClient wraps those commands so each call returns a promise. That is separate from a ticker or trade subscription, which keeps pushing events.

submitNewSpotOrder is the spot entry point. Under the hood it calls sendWSAPIRequest on the wsApiSpotV1 connection with the channel spot.order. You can call sendWSAPIRequest yourself if you want the lower-level form. Both are awaitable.

Imported example

JavaScript
import { WebsocketAPIClient } from "kucoin-api";

const wsClient = new WebsocketAPIClient({
  apiKey: process.env.API_KEY,
  apiSecret: process.env.API_SECRET,
  apiPassphrase: process.env.API_PASSPHRASE,
});

const response = await wsClient.submitNewSpotOrder({
  side: "buy",
  symbol: "BTC-USDT",
  type: "limit",
  price: "150000",
  size: "0.0001",
});

console.log(response);

The price in that example is taken from the SDK readme so the sample is obvious as a shape, not a suggested trade. A live key with trade permission will still send it. Futures and margin have their own methods on the same class (submitFuturesOrder, submitMarginOrder). See examples/WebSockets/WS-API/ws-api-client.ts.

This promise-style trading client exists on kucoin-api. It is not a feature of every Siebly SDK. bitmart-api has subscription streams and no WebSocket request API. coinbase-api exposes sendWSAPIRequest, but that method returns without sending a command. Check the package you are actually importing.

Before you run this in production

  • Read the key from a secret store at runtime. The automation key should not be allowed to withdraw.
  • Start with getTicker or getSymbols. Add the passphrase only when you need private data.
  • Back off when KuCoin rate-limits you. The client will not do that.
  • If a REST or WebSocket order call fails, look the order up by clientOid before you send it again.
  • On a WebSocket reconnect, rebuild any local order book from a REST snapshot plus the new stream. Resubscribe is automatic. Gap detection is not.
  • When you upgrade kucoin-api, read the changelog and rerun the calls you depend on. KuCoin’s docs stay the reference for what an endpoint accepts.

The Siebly SDK directory lists the other exchange packages if this integration is one venue in a larger app. For KuCoin spot, stay on kucoin-api and the quickstart.

Frequently Asked Questions

What is the KuCoin Spot API TypeScript SDK?

It is the kucoin-api package from Siebly. For spot, you construct a SpotClient. The client signs private requests, sets the timestamp, and exposes typed methods such as getTicker and submitOrder. KuCoin’s own documentation is still the reference for what each endpoint accepts.

Does kucoin-api support TypeScript and Node.js?

Yes. The npm package ships TypeScript declarations and both import and require entry points. The examples in the repo run on Node.js. Browser builds go through the webpack setup described in the package readme, using the Web Crypto API for signing.

Does the Siebly KuCoin SDK handle rate limits automatically?

No. kucoin-api sends the request you asked for and returns the response or throws. If KuCoin answers with a rate-limit error, your code waits and tries again later. The other Siebly exchange SDKs listed above behave the same way on this point.

Can the KuCoin SDK use WebSockets for order placement?

Yes. WebsocketAPIClient.submitNewSpotOrder() returns a promise for that order command. Subscriptions such as ticker are a different path: you listen on the update event and the messages keep coming. Confirm the request fields against the current KuCoin WebSocket API docs before you trade with it.

How should I store KuCoin API credentials in a TypeScript application?

Put API_KEY, API_SECRET, and API_PASSPHRASE in a secret manager and read them when the process starts. You need all three for any private call. Do not commit them, and do not paste them into a chat when you ask for help. Disable withdrawals on keys used by automation.

Can I test a KuCoin Spot API integration without using live credentials?

You can call public methods such as getTicker({ symbol: 'BTC-USDT' }) with new SpotClient() and no keys. Those requests still go to KuCoin’s live market-data API. This package does not include a working sandbox base URL. Private methods, including balances and orders, need real credentials.

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.