---
title: "KuCoin Spot API TypeScript SDK"
description: "Integrate the KuCoin Spot API TypeScript SDK in Node.js. Streamline authentication, signing, and awaitable WebSockets while keeping full rate limit control."
canonical: "https://siebly.io/blog/kucoin-spot-api-typescript-sdk-a-practical-integration-guide"
---

# 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.

## Technical Disclaimer

These articles are software engineering references for exchange API integrations. They are not financial, investment, legal, tax, compliance, or trading advice. Use public data, demo, testnet, or paper workflows first. Keep API credentials out of frontend code and disable withdrawal permissions for automation keys.

## Overview {#overview}

The [KuCoin Spot API TypeScript SDK](/sdk/kucoin/javascript) 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](/sdk/kucoin/javascript). Endpoint behavior still comes from [KuCoin’s API docs](https://www.kucoin.com/docs-new/introduction).

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

## Key Takeaways {#key-takeaways}

- Package name is [kucoin-api](/sdk/kucoin/javascript). 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 {#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:

| Client | Use it for |
| --- | --- |
| `SpotClient` | Spot and margin REST |
| `FuturesClient` | Futures REST |
| `BrokerClient` | Broker and sub-account REST |
| `UnifiedAPIClient` | KuCoin’s unified (Pro) REST endpoints |
| `WebsocketClient` | Public and private streams, spot and futures |
| `WebsocketAPIClient` | Trading commands over a WebSocket, returned as a promise |

## Public market data {#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.

```js title="Imported example"
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 {#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.

```js title="Imported example"
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.

```js title="Imported example"
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 {#what-stays-in-your-application}

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

| Responsibility | kucoin-api | Your application |
| --- | --- | --- |
| Authentication and signing | Signs private REST calls with key, secret, and passphrase. | Store the three values and choose the key’s permissions. |
| Timestamps | Sends `KC-API-TIMESTAMP`. Override with `customTimestampFn` if your clock drifts. | Keep the host clock close to KuCoin’s. |
| Request shapes | TypeScript types for most calls. | Match the fields to the current KuCoin docs. |
| REST retries | A failed call is thrown once. | Decide if that call is safe to send again. |
| Rate limits | No 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](/sdk/binance/javascript), [bitget-api](/sdk/bitget/javascript), `bitmart-api`, [bybit-api](/sdk/bybit/javascript), [coinbase-api](/sdk/coinbase/javascript), [gateio-api](/sdk/gate/javascript), [@siebly/htx-api](/sdk/htx/javascript), [@siebly/kraken-api](/sdk/kraken/javascript), [okx-api](/sdk/okx/javascript)). 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 {#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.

```js title="Imported example"
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 {#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.

```js title="Imported example"
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](/sdk/kucoin/javascript). It is not a feature of every Siebly SDK. `bitmart-api` has subscription streams and no WebSocket request API. [coinbase-api](/sdk/coinbase/javascript) exposes `sendWSAPIRequest`, but that method returns without sending a command. Check the package you are actually importing.

## Before you run this in production {#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](/sdk/kucoin/javascript), 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](/sdk) 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](/sdk/kucoin/javascript).

## Frequently Asked Questions {#frequently-asked-questions}

### What is the KuCoin Spot API TypeScript SDK? {#what-is-the-kucoin-spot-api-typescript-sdk}

It is the [kucoin-api](/sdk/kucoin/javascript) 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? {#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? {#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? {#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? {#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? {#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

- [Bitget API TypeScript SDK: A Practical Integration Guide](/blog/bitget-api-typescript-sdk-a-practical-integration-guide)
- [KuCoin Futures API Node.js SDK: 2026 Integration Guide](/blog/kucoin-futures-api-nodejs-sdk-2026-integration-guide)
- [KuCoin Node.js SDK: A Guide to Modern Exchange Integration](/blog/kucoin-nodejs-sdk-a-guide-to-modern-exchange-integration)


## Related Siebly Resources

- [Binance JavaScript SDK](/sdk/binance/javascript)
- [Bybit JavaScript SDK](/sdk/bybit/javascript)
- [OKX JavaScript SDK](/sdk/okx/javascript)
- [Siebly SDK directory](/sdk)
- [Exchange State Management](/ai/exchange-state)
