---
title: "Bitget API TypeScript SDK: A Practical Integration Guide"
description: "Master the Bitget API TypeScript SDK with this guide. Connect REST and awaitable WebSocket operations cleanly in Node.js using bitget-api from Siebly.io."
canonical: "https://siebly.io/blog/bitget-api-typescript-sdk-a-practical-integration-guide"
---

# Bitget API TypeScript SDK: A Practical Integration Guide

Master the Bitget API TypeScript SDK with this guide. Connect REST and awaitable WebSocket operations cleanly in Node.js using bitget-api from Siebly.io.

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

Private Bitget calls need a signature, a timestamp, and the passphrase you set when you created the key. Streams sit on a different client from order calls. The [bitget-api](/sdk/bitget/javascript) package from Siebly.io is the TypeScript client for that work. Setup notes also live in the [Bitget JavaScript SDK guide](/sdk/bitget/javascript).

This guide follows the clients in the current package: a public REST call, a signed REST call, a market stream, and an order sent on Bitget's V3 WebSocket API. The client signs requests, sends timestamps, and types the inputs. Your code still decides how fast to call, and what to do when Bitget returns a limit error.

Bitget's docs are the contract. Use the [V3 Unified Trading Account docs](https://www.bitget.com/api-doc/uta/intro) or the [V2 docs](https://www.bitget.com/api-doc/common/intro), depending on the account. The SDK is how you call those endpoints from Node.js, TypeScript, or plain JavaScript.

## Key takeaways {#key-takeaways}

- Use `RestClientV3` and `WebsocketClientV3` on a Unified Trading Account. Use `RestClientV2` and `WebsocketClientV2` on a classic account.
- Public market calls need no keys. Private calls need `apiKey`, `apiSecret`, and `apiPass` together.
- `WebsocketAPIClient` places V3 orders over a WebSocket and returns a promise. Stream updates come from `WebsocketClientV3`. Treat those as separate paths.
- The WebSocket client reconnects and resubscribes. It does not retry a failed REST call, and it does not throttle you.
- Start with a public call. For private calls, turn on `demoTrading` and use demo keys.



## Which client to construct {#which-client-to-construct}

[bitget-api](/sdk/bitget/javascript) ships five clients:

- `RestClientV3` for V3 REST on a Unified Trading Account
- `WebsocketClientV3` for V3 market and account streams
- `WebsocketAPIClient` for V3 orders over a WebSocket, returned as a promise
- `RestClientV2` for V2 REST on a classic account
- `WebsocketClientV2` for V2 streams

V3 account calls, private streams, and WebSocket orders need a Unified Trading Account. After you upgrade, V2 account calls stop working until you switch the account back to classic mode. If the account is still classic, stay on the V2 clients.

The package signs with HMAC by default, through the Web Crypto API. An RSA key works too: put the PEM private key in `apiSecret`, and keep the `BEGIN PRIVATE KEY` header in the string so the client treats it as RSA. You still pass `apiPass`. That value is the passphrase from API key creation, not the Bitget login password.

There is no V1 REST client in the current package. Use V2 or V3.

## Install the package and call public data {#install-the-package-and-call-public-data}

```bash title="Imported example"
npm install bitget-api
```

Private signing uses Web Crypto (`globalThis.crypto`). Current Node LTS has it. If `crypto` is missing, the client tells you to move to Node LTS (v22 or newer), or to pass `customSignMessageFn` and sign with `node:crypto` yourself. The repo example for that is `examples/auth/fasterHmacSign.ts`.

Load keys from the environment. Do not commit them, and do not print them. A public client does not need keys at all.

This is the V3 candle call from `examples/V3 - UTA/Rest/rest-public-UTA-spot.ts`. The published package import is [bitget-api](/sdk/bitget/javascript).

```ts title="Imported example"
import { RestClientV3 } from "bitget-api";

const restClient = new RestClientV3();

const candles = await restClient.getCandles({
  symbol: "BTCUSDT",
  category: "SPOT",
  interval: "1m",
});

console.log(candles.data.length);
```

On a classic account, the matching public call is `RestClientV2.getSpotCandles()`:

```ts title="Imported example"
import { RestClientV2 } from "bitget-api";

const restClient = new RestClientV2();

const candles = await restClient.getSpotCandles({
  symbol: "BTCUSDT",
  granularity: "1min",
  limit: "100",
});

console.log(candles.data.length);
```

`require('bitget-api')` works the same way if the project is CommonJS. A browser build is available through the package webpack bundle.

## Sign a private REST call {#sign-a-private-rest-call}

Pass all three credentials. If you set any one of them and leave another empty, the constructor throws: key, secret, and passphrase are all required.

`demoTrading: true` sends Bitget's demo header (`paptrading: 1`) and expects demo keys. Live keys on that flag will not do what you want. Bitget documents the demo REST setup [here](https://www.bitget.com/api-doc/common/demotrading/restapi).

```ts title="Imported example"
import { RestClientV3 } from "bitget-api";

const client = new RestClientV3({
  apiKey: process.env.API_KEY_COM,
  apiSecret: process.env.API_SECRET_COM,
  apiPass: process.env.API_PASS_COM,
  // demoTrading: true,
});

try {
  const balances = await client.getBalances();
  console.log(balances.data);
} catch (error) {
  console.error("request failed:", error);
}
```

That pattern is the private example in `examples/V3 - UTA/Rest/rest-private.ts`. The client builds the timestamp and signature. The REST receive window defaults to 5000 ms. Set `recvWindow` on the client if you need a different window.

A completed HTTP call can still be a failed order or a rejected read. If Bitget answers with HTTP 200 and a `code` other than `00000`, the client throws. The thrown object carries the status, message, and body. Before it is thrown, `apiSecret` and `apiPass` are stripped out of `requestOptions`. Log the body. Do not log the client options you started with.

The client does not retry that failure. If you retry, do it in your code, and only for calls that are safe to send twice. A place-order call is not one of those unless you have your own idempotency key and you know Bitget will honor it.

Same story for rate limits. [bitget-api](/sdk/bitget/javascript) does not queue, delay, or throttle requests. The other Siebly exchange clients in this set (Binance, Bitmart, Bybit, Coinbase, Gate, HTX, Kraken, KuCoin, OKX) do not throttle for you either. Pace the calls yourself, and decide what a limit response means for that job.

V3 REST order fields are typed as `PlaceOrderRequestV3`. Category lives on the object, in Bitget's REST spelling: `SPOT`, `MARGIN`, `USDT-FUTURES`, `COIN-FUTURES`, `USDC-FUTURES`. Keep that next to you when you look at the WebSocket sample below. The WebSocket category strings are different.



## Streams and awaitable WebSocket calls {#streams-and-awaitable-websocket-calls}

Subscribing to a topic and placing an order are different clients.

`WebsocketClientV3` is the stream client. It connects when you subscribe, sends heartbeats, reconnects if the socket drops, and resubscribes to the topics it was holding. Listen for `update` when you want the data. `reconnected` tells you the socket is back. Your own state still has to be rebuilt from REST or from the next events. A reconnect event is not a full account snapshot.

Public ticker subscription, from `examples/V3 - UTA/Websocket/ws-public.ts`:

```ts title="Imported example"
import { WebsocketClientV3, WS_KEY_MAP } from "bitget-api";

const wsClient = new WebsocketClientV3();

wsClient.on("update", (data) => {
  console.log("WS message", data);
});

wsClient.on("exception", (data) => {
  console.log("WS error", data);
});

wsClient.on("reconnected", (data) => {
  console.log("WS reconnected", data?.wsKey);
});

wsClient.subscribe(
  {
topic: "ticker",
payload: {
instType: "spot",
symbol: "BTCUSDT",
},
  },
  WS_KEY_MAP.v3Public,
);
```

Account and order streams need keys, and on V3 the account topics use `instType: 'UTA'` on the private socket:

```ts title="Imported example"
import { WebsocketClientV3, WS_KEY_MAP } from "bitget-api";

const wsClient = new WebsocketClientV3({
  apiKey: process.env.API_KEY_COM,
  apiSecret: process.env.API_SECRET_COM,
  apiPass: process.env.API_PASS_COM,
  // demoTrading: true,
});

wsClient.on("update", (data) => {
  console.log("WS message", data);
});

wsClient.subscribe(
  {
topic: "order",
payload: {
instType: "UTA",
},
  },
  WS_KEY_MAP.v3Private,
);
```

`WebsocketAPIClient` is the awaitable path. It wraps `WebsocketClientV3` and returns a promise that settles when the matching response arrives. This needs a V3 Unified Trading Account key. The call below is the one in `examples/V3 - UTA/WS-API/ws-api-client-trade.ts`. Running it sends an order. Leave `demoTrading` on unless you mean to trade.

```ts title="Imported example"
import { WebsocketAPIClient } from "bitget-api";

const wsClient = new WebsocketAPIClient({
  apiKey: process.env.API_KEY_COM,
  apiSecret: process.env.API_SECRET_COM,
  apiPass: process.env.API_PASS_COM,
  // demoTrading: true,
});

try {
  const res = await wsClient.submitNewOrder("spot", {
orderType: "limit",
price: "100",
qty: "0.1",
side: "buy",
symbol: "BTCUSDT",
timeInForce: "gtc",
  });

  console.log("submitNewOrder result:", res);
} catch (error) {
  console.error("submitNewOrder failed:", error);
}
```

The category is the first argument here: `spot`, `usdt-futures`, `coin-futures`, or `usdc-futures`. On REST, the same idea is a field named `category` with values like `SPOT` and `USDT-FUTURES`. Those strings are not interchangeable. `reduceOnly` differs too: REST uses `yes` and `no`, the WebSocket place-order params use `YES` and `NO`.

By default `WebsocketAPIClient` logs connection events. Set `attachEventListeners: false` and listen on `wsClient.getWSClient()` if you want to handle `open`, `reconnect`, and `reconnected` yourself.

The promise resolving means Bitget answered that request. It does not mean your stream handler has already seen the matching order event. Read the response in the order path. Read fills and order updates from the stream path.

If you call `placeBatchOrders`, read each item in the response. That call resolves even when individual orders are rejected. Check `code` and `msg` on each order.

## Check the integration before you add more {#check-the-integration-before-you-add-more}

Use a short sequence:

1. Read the method on `RestClientV3` or `RestClientV2` and the matching page in Bitget's docs.
2. Run one public call and check the shape you actually branch on. For V3 candles that is `response.data`.
3. For anything private, use demo keys with `demoTrading: true`. Turn off withdrawal permission on keys that software holds.
4. Force a bad call, such as a missing passphrase or a symbol the endpoint does not accept, and make sure the error reaches the caller.
5. Pin the installed version. Before a bump, read the [Siebly SDK release notes](/releases) and run the same calls again.

A test can show that you built the request, read the response, and surfaced the error. It cannot tell you how that workflow behaves in a live market.

Keep the exchange calls in one module. Let the rest of the app see balances, orders, and errors in whatever shape you actually store. The SDK client is that boundary. Pacing, retries, and what you do after a disconnect stay in the app.

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

### What is the Bitget API TypeScript SDK? {#what-is-the-bitget-api-typescript-sdk}

It is the [bitget-api](/sdk/bitget/javascript) package: a TypeScript client for Bitget V2 and V3 REST and WebSockets, usable from JavaScript and Node.js. It signs requests, sends timestamps, and types the request and response objects. V3 WebSocket orders go through `WebsocketAPIClient`. Bitget's docs still define the endpoint behavior.

### How do I install it? {#how-do-i-install-it}

`npm install bitget-api`

Import `RestClientV3`, `RestClientV2`, `WebsocketClientV3`, `WebsocketClientV2`, or `WebsocketAPIClient` from `bitget-api`. Check the [Bitget JavaScript SDK guide](/sdk/bitget/javascript) if the import in an old snippet does not match the version you installed.

### Does the SDK handle rate limits? {#does-the-sdk-handle-rate-limits}

No. Nothing in `bitget-api` delays or batches calls to stay under Bitget's limits. The same is true of the other Siebly exchange SDKs. Your process has to pace requests and react when Bitget says you hit a limit.

There is also no REST retry policy. If a call throws, it stays thrown until your code decides to send it again.

### Can I use it with Node.js and TypeScript? {#can-i-use-it-with-node-js-and-typescript}

Yes. The library is written in TypeScript and the npm build works from TypeScript or JavaScript, including `require`. Private calls need Web Crypto, which current Node LTS provides. The package also builds a browser bundle.

### How do I test before using live keys? {#how-do-i-test-before-using-live-keys}

Call a public method such as `getCandles` with `new RestClientV3()` and no credentials. For private methods, create demo API keys and construct the client with `demoTrading: true`. Confirm a failure still shows up as an error, and confirm logs do not contain the secret or passphrase.

### Can WebSocket calls be awaited? {#can-websocket-calls-be-awaited}

Yes, for V3 operations exposed on `WebsocketAPIClient`, including `submitNewOrder`. The promise resolves or rejects when the matching response arrives. Ongoing events are a subscription on `WebsocketClientV3`, not the return value of that call. The account has to be on the Unified Trading Account, and the key has to be a V3 key.

## Related articles

- [Bitget API SDK for TypeScript: Node.js Guide (2026)](/blog/bitget-api-sdk-for-typescript-nodejs-guide-2026)
- [KuCoin Spot API TypeScript SDK: A Practical Integration Guide](/blog/kucoin-spot-api-typescript-sdk-a-practical-integration-guide)
- [Bitget API SDK TypeScript: Building Production-Ready Node.js Integrations in 2026](/blog/bitget-api-sdk-typescript-building-production-ready-nodejs-integrations-in-2026)


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