---
title: "Coinbase Pro to Advanced Trade Migration Guide"
description: "Learn how to migrate from Coinbase Pro API to Advanced Trade Node.js. This guide covers V3 auth, WebSockets, and idempotency using the coinbase-api SDK."
canonical: "https://siebly.io/blog/coinbase-pro-to-advanced-trade-migration-guide"
---

# Coinbase Pro to Advanced Trade Migration Guide

Learn how to migrate from Coinbase Pro API to Advanced Trade Node.js. This guide covers V3 auth, WebSockets, and idempotency using the coinbase-api SDK.

## 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 Coinbase Pro API shut down on June 6, 2024. If you still have a Node.js stack talking to Pro private endpoints, those calls fail. Retail trading moved to Advanced Trade V3. Institutional Pro access moved to Coinbase Exchange. Those are different APIs, different auth, different clients. This guide is for the retail path: migrate from coinbase pro api to advanced trade nodejs.

The [coinbase-api](/sdk/coinbase/javascript) SDK is the implementation layer we use for that work. It signs every private REST call with a short-lived JWT, attaches a JWT to private WebSocket subscribe messages, and gives you typed request shapes. It does not rate-limit or throttle for you. That part stays in your code.

## Key Takeaways {#key-takeaways}

- Pro used API key + secret + passphrase and HMAC headers. Advanced Trade uses Cloud API keys: a key name and a private key (ECDSA or Ed25519). Auth is a JWT in an `Authorization: Bearer` header, not HMAC-SHA256.
- HMAC with `CB-ACCESS-KEY`, `CB-ACCESS-SIGN`, `CB-ACCESS-TIMESTAMP`, and `CB-ACCESS-PASSPHRASE` is still how Coinbase Exchange and International work. Prime is the same idea with different header names: `X-CB-ACCESS-KEY`, `X-CB-ACCESS-SIGNATURE`, `X-CB-ACCESS-TIMESTAMP`, `X-CB-ACCESS-PASSPHRASE`. Do not copy any of that signing code onto Advanced Trade.
- Orders go over REST. Coinbase Advanced Trade has no request/response WebSocket API for placing orders. `WebsocketClient.sendWSAPIRequest()` in this package returns immediately and does nothing. Other Siebly SDKs wrap those exchanges' real WebSocket APIs: [binance](/sdk/binance/javascript), [bybit-api](/sdk/bybit/javascript), [okx-api](/sdk/okx/javascript), [@siebly/kraken-api](/sdk/kraken/javascript), [@siebly/htx-api](/sdk/htx/javascript), [bitget-api](/sdk/bitget/javascript), [gateio-api](/sdk/gate/javascript), [kucoin-api](/sdk/kucoin/javascript). `bitmart-api` does not, because BitMart does not ship that API. Coinbase does not have one either.
- Public market data lives on `wss://advanced-trade-ws.coinbase.com`. Private user data lives on `wss://advanced-trade-ws-user.coinbase.com`. The SDK reconnects and resubscribes on drop.
- `client_order_id` is required by Coinbase. The SDK generates one if you omit it, and prefixes custom values with `cbnode`.



## Coinbase Pro to Advanced Trade: Context & Deprecation {#coinbase-pro-to-advanced-trade-context-deprecation}

Coinbase Pro accounts were disabled on December 1, 2023. The Pro API itself was deprecated on June 6, 2024. Retail bots need the Advanced Trade V3 REST and WebSocket APIs. Institutional users should look at Coinbase Exchange instead (`CBExchangeClient` in the same package), which still uses passphrase HMAC auth.

You cannot reuse Pro keys. You cannot reuse Pro paths like `/products`.

### Why Legacy Pro Integrations Fail {#why-legacy-pro-integrations-fail}

Pro signed every private call with HMAC-SHA256 over `timestamp + method + path + body`, then sent `CB-ACCESS-*` headers plus a passphrase. Advanced Trade dropped the passphrase. Cloud API keys are a name (often `organizations/.../apiKeys/...`) and a private key. The SDK detects ECDSA PEM keys (`ES256`) and Ed25519 keys (`EdDSA`) automatically.

If you send Pro credentials or HMAC headers to V3, Coinbase rejects the request. The signature format is a JWT, not a base64 HMAC. The header is `Authorization: Bearer`.

### The 2026 API Landscape for Coinbase {#the-2026-api-landscape-for-coinbase}

Advanced Trade is the retail gateway for spot and futures. Coinbase currently lists 550+ spot pairs. Cloud API keys support IP allowlists (recommended, not required) and scoped permissions (`view`, `trade`, `transfer`).

REST traffic is commonly cited at 10,000 requests per hour per API key under Coinbase App policy. WebSocket connections are limited to 8 per second per IP. Unauthenticated WebSocket messages are a separate 8 per second per IP cap. The SDK does not enforce those limits. You own the queue and backoff.

The [coinbase-api](/sdk/coinbase/javascript) package covers Advanced Trade, App, Exchange, International, Prime, and Commerce. For this migration you want `CBAdvancedTradeClient` and `WebsocketClient`.

## Mapping Authentication: JWT, not HMAC {#mapping-authentication-jwt-not-hmac}

This is the breaking change people get wrong when they migrate from coinbase pro api to advanced trade nodejs. Pro: key, secret, passphrase. Advanced Trade: Cloud API key name plus private key. No passphrase.

JWT lifetime in the SDK defaults to 120 seconds (`jwtExpiresSeconds`). Coinbase expects a fresh JWT per request. The SDK builds one on every private REST call and on every authenticated WebSocket subscribe.

### What the SDK actually signs {#what-the-sdk-actually-signs}

For REST it builds a JWT with `iss: 'cdp'`, `sub` and `kid` set to the key name, `nbf`/`exp` from the local clock, and a `uri` claim of `METHOD host/path`. Algorithm is `ES256` or `EdDSA` depending on the key. That token goes out as:

```text title="Imported example"
Authorization: Bearer
```

For private WebSocket subscribe messages it builds a similar JWT (no `uri` claim) and puts it on the subscribe payload as `jwt`.

Clock drift still matters because of `nbf` and `exp`. Keep NTP honest. The client also exposes `fetchLatencySummary()` if you want to compare local time against Coinbase server time.

Do not implement HMAC-SHA256 and attach `CB-ACCESS-SIGN`. That is Exchange and International. Prime uses `X-CB-ACCESS-SIGNATURE` instead of `CB-ACCESS-SIGN`. Mixing any of that onto Advanced Trade is the fastest way to a wall of 401s.

If you actually need Coinbase Exchange, that is a different client and a passphrase:

```js title="Imported example"
const { CBExchangeClient } = require("coinbase-api");
// import { CBExchangeClient } from 'coinbase-api';

const exchangeClient = new CBExchangeClient({
  apiKey: process.env.EXCHANGE_API_KEY,
  apiSecret: process.env.EXCHANGE_API_SECRET,
  // Passphrase you set when creating the Exchange key, not your account password.
  apiPassphrase: process.env.EXCHANGE_API_PASSPHRASE,
  // useSandbox: true,
});
```

### Installing and creating a client {#installing-and-creating-a-client}

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

```js title="Imported example"
const { CBAdvancedTradeClient } = require("coinbase-api");
// import { CBAdvancedTradeClient } from 'coinbase-api';

// ECDSA (PEM) or Ed25519 (base64). The client detects both.
const client = new CBAdvancedTradeClient({
  apiKey: process.env.API_KEY_NAME,
  apiSecret: process.env.API_PRIVATE_KEY,
  // Or pass the downloaded CDP JSON:
  // cdpApiKey: { name: '...', privateKey: '...' },
});

async function getAccounts() {
  try {
const accounts = await client.getAccounts({ limit: 10 });
console.log(accounts);

if (accounts.accounts.length > 0) {
const accountDetails = await client.getAccount({
account_id: accounts.accounts[0].uuid,
});
console.log(accountDetails);
}
  } catch (e) {
console.error("Get accounts error: ", e);
  }
}

getAccounts();
```

Public REST needs no keys. Same client, empty options:

```js title="Imported example"
const { CBAdvancedTradeClient } = require("coinbase-api");

const client = new CBAdvancedTradeClient({});

async function publicCalls() {
  const serverTime = await client.getServerTime();
  console.log(serverTime);

  const productBook = await client.getPublicProductBook({
product_id: "BTC-USD",
limit: 10,
  });
  console.log(productBook);

  const { products } = await client.getPublicProducts({
product_type: "SPOT",
  });
  const btc = products.find((p) => p.product_id === "BTC-USD");
  console.log(btc?.base_increment, btc?.quote_increment, btc?.base_min_size);
}

publicCalls().catch(console.error);
```

Keep keys in env or a secret manager. Scope them to `view` and `trade`. Leave withdrawal/`transfer` off unless you actually need it. IP allowlisting is extra defense, not a Coinbase requirement.

The SDK signs for you. It does not throttle. Stay under the hourly REST cap yourself.

## WebSocket Migration: Market Data and User Streams {#websocket-migration-market-data-and-user-streams}

The Pro feed URL is gone. Advanced Trade splits public and private traffic:

- Market data: SDK `wsKey` `advTradeMarketData`, URL `wss://advanced-trade-ws.coinbase.com`
- User data: SDK `wsKey` `advTradeUserData`, URL `wss://advanced-trade-ws-user.coinbase.com`

Ticker, candles, level2, status, ticker_batch, and similar public channels go to `advTradeMarketData`. On `advTradeUserData` you subscribe to `user` (orders and fills) and `futures_balance_summary` (futures balances). Subscribe on the user key and the SDK injects the JWT. You do not send a separate auth handshake.

Coinbase drops the socket if it does not get a subscribe within 5 seconds of connect. The SDK sends stored topics as soon as the socket is up.

Coinbase has no sandbox for Advanced Trade WebSockets. `useSandbox` only works for Exchange and International. Prime, App, Advanced Trade, and Commerce have no sandbox URL. If you flip `useSandbox` on those, the SDK has nowhere to send the request.

### Public market data {#public-market-data}

```js title="Imported example"
const { WebsocketClient } = require("coinbase-api");

const client = new WebsocketClient();

client.on("open", (data) => {
  console.log("open", data?.wsKey);
});

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

client.on("response", (data) => {
  console.info("response", JSON.stringify(data));
});

client.on("reconnect", (data) => console.log("reconnect", data));
client.on("reconnected", (data) => console.log("reconnected", data));
client.on("close", (data) => console.error("close", data));
client.on("exception", (data) => console.error("exception", data));

client.subscribe(
  {
topic: "ticker",
payload: { product_ids: ["ETH-USD", "BTC-USD"] },
  },
  "advTradeMarketData",
);

client.subscribe(
  [
{ topic: "heartbeats" },
{ topic: "candles", payload: { product_ids: ["ETH-USD"] } },
{
topic: "market_trades",
payload: { product_ids: ["ETH-USD", "BTC-USD"] },
},
{
topic: "status",
payload: { product_ids: ["ETH-USD", "BTC-USD"] },
},
{
topic: "ticker_batch",
payload: { product_ids: ["ETH-USD", "BTC-USD"] },
},
{ topic: "level2", payload: { product_ids: ["ETH-USD", "BTC-USD"] } },
  ],
  "advTradeMarketData",
);
```

Ticker payloads changed from Pro. Parse the V3 schema, do not reuse old field names.

Subscribe to `heartbeats` if you want Coinbase's own keepalive channel. The SDK also pings the socket and reconnects on close/error, then resubscribes stored topics. Listen for `reconnect` and `reconnected` if you keep local books.

Stay within 8 unauthenticated messages per second per IP, and 8 new connections per second per IP. Filter in the `update` handler so you only work on pairs you trade.

### Private user stream {#private-user-stream}

```js title="Imported example"
const { WebsocketClient } = require("coinbase-api");

const client = new WebsocketClient({
  apiKey: process.env.API_KEY_NAME,
  apiSecret: process.env.API_PRIVATE_KEY,
});

client.on("update", (data) => {
  console.info("user event", JSON.stringify(data));
});

client.on("response", (data) => {
  console.info("response", JSON.stringify(data));
});

client.on("exception", (data) => console.error("exception", data));

// Any subscribe on advTradeUserData is signed automatically.
client.subscribe("user", "advTradeUserData");
client.subscribe("futures_balance_summary", "advTradeUserData");
```

Use `user` for fills and order updates. Use `futures_balance_summary` for futures balances. Polling `getOrders()` for every state change burns your hourly budget.

You cannot place an order over this socket and `await` an ack. That pattern exists in Siebly SDKs for exchanges that ship a WebSocket API. Coinbase Advanced Trade does not. `sendWSAPIRequest` in [coinbase-api](/sdk/coinbase/javascript) is unimplemented. It returns `undefined`.

This is what the same idea looks like on Binance, where the exchange actually has a WebSocket API:

```js title="Imported example"
const { WebsocketAPIClient } = require("binance");

const ws = new WebsocketAPIClient({
  api_key: process.env.API_KEY_COM,
  api_secret: process.env.API_SECRET_COM,
});

async function placeOnSocket() {
  const result = await ws.submitNewSpotOrder({
symbol: "BTCUSDT",
side: "SELL",
type: "LIMIT",
timeInForce: "GTC",
price: "23416.10000000",
quantity: "0.00847000",
  });
  console.log(result);
}

placeOnSocket().catch(console.error);
```

Bybit is `new WebsocketAPIClient({ key, secret })` then `submitNewOrder()`. OKX takes an `accounts` array with `apiKey`, `apiSecret`, `apiPass`. Bitget needs `apiPass`. KuCoin needs `apiPassphrase`. Kraken, HTX, and Gate take `apiKey` plus `apiSecret`. None of that applies here.

Place Coinbase orders with `CBAdvancedTradeClient.submitOrder()`. Watch the `user` channel for the result.



## Engineering Best Practices for Order Management {#engineering-best-practices-for-order-management}

Pro order bodies used flat fields (`size`, `price`, `type`). V3 wraps size and price inside `order_configuration`. The SDK keys are:

- Market IOC: `market_market_ioc`
- Limit GTC: `limit_limit_gtc`
- Limit GTD: `limit_limit_gtd`
- Limit FOK: `limit_limit_fok`
- SOR limit IOC: `sor_limit_ioc`
- Stop-limit GTC/GTD: `stop_limit_stop_limit_gtc`, `stop_limit_stop_limit_gtd`
- TWAP: `twap_limit_gtd`
- Brackets: `trigger_bracket_gtc`, `trigger_bracket_gtd`

`client_order_id` is required by the API. If you omit it, the SDK fills `client.generateNewOrderId()` (`cbnode` plus a 14-character nanoid). If you pass your own id without that prefix, the SDK prepends `cbnode` and logs a warning. Reuse the same id on retry so Coinbase treats it as one order.

### Submit a market and a limit order {#submit-a-market-and-a-limit-order}

```js title="Imported example"
const { CBAdvancedTradeClient } = require("coinbase-api");

const client = new CBAdvancedTradeClient({
  apiKey: process.env.API_KEY_NAME,
  apiSecret: process.env.API_PRIVATE_KEY,
});

async function submitMarketSell() {
  try {
const result = await client.submitOrder({
product_id: "BTC-USDT",
side: "SELL",
client_order_id: client.generateNewOrderId(),
order_configuration: {
market_market_ioc: { base_size: "0.001" },
},
});
console.log(result);
  } catch (e) {
console.error("Send new order error: ", e);
  }
}

async function submitLimitBuy() {
  try {
const result = await client.submitOrder({
product_id: "BTC-USDT",
side: "BUY",
client_order_id: client.generateNewOrderId(),
order_configuration: {
limit_limit_gtc: {
base_size: "0.001",
limit_price: "50000.00",
},
},
});
console.log(result);
  } catch (e) {
console.error("Submit limit order error: ", e);
  }
}

submitMarketSell();
submitLimitBuy();
```

Statuses are not just PENDING then FILLED. Coinbase uses `PENDING`, `OPEN`, `FILLED`, `CANCELLED`, `EXPIRED`, `FAILED`, `QUEUED`, `CANCEL_QUEUED`, `EDIT_QUEUED`, and `UNKNOWN_ORDER_STATUS`. Track those off the `user` channel, then reconcile with `getOrder` / `getOrders` when you need a hard snapshot.

```js title="Imported example"
async function getOrders() {
  try {
const orders = await client.getOrders({ limit: 5 });
console.log(orders);

if (orders.orders.length > 0) {
const details = await client.getOrder({
order_id: orders.orders[0].order_id,
});
console.log(details);
}
  } catch (e) {
console.error("Error: ", e);
  }
}

getOrders();
```

### Increments and rate limits {#increments-and-rate-limits}

Fetch product specs before you send size and price. Increments differ per product. Public product data does not need keys:

```js title="Imported example"
const { products } = await client.getPublicProducts({ product_type: "SPOT" });
const btc = products.find((p) => p.product_id === "BTC-USD");
// btc.base_increment, btc.quote_increment, btc.base_min_size
```

The authenticated twin is `getProducts({ product_type: "SPOT" })` on the same client. Same increment fields.

REST: plan around 10,000 requests per hour per key (Coinbase App policy, the most specific published number), and watch 429s plus rate-limit headers. WebSocket: 8 connections per second per IP, and 8 unauthenticated messages per second per IP. Token bucket or leaky bucket in your process. The SDK will not do this.

## Modernizing Your Integration with the Siebly coinbase-api SDK {#modernizing-your-integration-with-the-siebly-coinbase-api-sdk}

A hand-rolled V3 client means you own JWT construction, key-type detection, header injection, subscribe signing, reconnect, and type drift every time Coinbase changes a field. [coinbase-api](/sdk/coinbase/javascript) already does that for Advanced Trade and the other Coinbase API groups in the same npm package.

It is TypeScript-first. Request and response shapes are typed. Same patterns as the other Siebly exchange SDKs ([binance](/sdk/binance/javascript), [bybit-api](/sdk/bybit/javascript), [okx-api](/sdk/okx/javascript), [kucoin-api](/sdk/kucoin/javascript), [gateio-api](/sdk/gate/javascript), [bitget-api](/sdk/bitget/javascript), `bitmart-api`, [@siebly/kraken-api](/sdk/kraken/javascript), [@siebly/htx-api](/sdk/htx/javascript)). Coding agents work better against those types and the bundled `llms.txt`. See the [Siebly AI Prompt Framework and Skills](/ai) if you generate integration code with an LLM.

What it does not do: rate limits, throttling, or Coinbase WebSocket order entry (because Coinbase does not offer it).

### Getting started {#getting-started}

Install `coinbase-api`. Pass the Cloud API key name and private key (or `cdpApiKey`). Public REST and public sockets need no keys. Private REST and `advTradeUserData` do.

Docs and more samples: [Siebly Coinbase SDK documentation](/sdk/coinbase/javascript). The GitHub repo also has runnable examples under `examples/AdvancedTrade/` (REST orders, accounts, public and private sockets).

Migrate from coinbase pro api to advanced trade nodejs with that client, not with a leftover Pro HMAC wrapper.

## Modernizing Your Trading Infrastructure {#modernizing-your-trading-infrastructure}

Pro is gone. Advanced Trade wants JWT Cloud keys, /api/v3/brokerage paths, nested order_configuration, and two WebSocket hosts. client_order_id keeps retries idempotent. The user channel keeps local order state honest.

`CBAdvancedTradeClient` and `WebsocketClient` from [coinbase-api](/sdk/coinbase/javascript) cover signing, reconnect, and types. You still write the rate limiter. [Explore the Siebly Coinbase JavaScript SDK](/sdk/coinbase/javascript) and start from the Advanced Trade examples rather than a Pro leftover.

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

### Can I still use my Coinbase Pro API keys for Advanced Trade? {#can-i-still-use-my-coinbase-pro-api-keys-for-advanced-trade}

No. Pro keys were key + secret + passphrase. Advanced Trade keys are a Cloud API key name and a private key (ECDSA PEM or Ed25519). Create new credentials on the Coinbase Developer Platform. Scope them as tightly as you can.

If you were on Pro as an institution, you likely want Coinbase Exchange keys and `CBExchangeClient`, which still uses HMAC and a passphrase (`CB-ACCESS-*` headers). Prime is HMAC too, but the headers are `X-CB-ACCESS-*`.

### What is the main difference between Coinbase Pro and Advanced Trade APIs? {#what-is-the-main-difference-between-coinbase-pro-and-advanced-trade-apis}

Auth, paths, and order shape. Pro HMAC headers and `/products` are gone. V3 uses JWT Bearer auth and `/api/v3/brokerage/...`. Orders nest size and price under `order_configuration`. Market data and user data use two different WebSocket URLs.

### How do I handle authentication in the Coinbase Advanced Trade V3 API? {#how-do-i-handle-authentication-in-the-coinbase-advanced-trade-v3-api}

Generate a JWT (ES256 or EdDSA) per private REST request and put it in `Authorization: Bearer`. Private WebSocket subscribe messages carry a `jwt` field. [coinbase-api](/sdk/coinbase/javascript) does both. You pass `apiKey` + `apiSecret` (or `cdpApiKey`) and call methods. Do not build HMAC `CB-ACCESS-SIGN` headers for Advanced Trade.

### Does the Siebly coinbase-api SDK handle rate limiting automatically? {#does-the-siebly-coinbase-api-sdk-handle-rate-limiting-automatically}

No. That is intentional. Put a leaky bucket or token bucket in your app. Treat 10,000 REST requests per hour per key as the headline cap. WebSocket: 8 connections per second per IP, and 8 unauthenticated messages per second per IP. Watch 429s.

### What is the awaitable WebSocket pattern in Siebly SDKs? {#what-is-the-awaitable-websocket-pattern-in-siebly-sdks}

On exchanges that expose a WebSocket API, several Siebly SDKs wrap commands in promises (`WebsocketAPIClient` on [binance](/sdk/binance/javascript), [bybit-api](/sdk/bybit/javascript), [okx-api](/sdk/okx/javascript), [@siebly/kraken-api](/sdk/kraken/javascript), [@siebly/htx-api](/sdk/htx/javascript), [bitget-api](/sdk/bitget/javascript), [gateio-api](/sdk/gate/javascript), [kucoin-api](/sdk/kucoin/javascript)). You send an order on the socket and await the ack. `bitmart-api` has no `WebsocketAPIClient` because BitMart does not offer that API.

Coinbase Advanced Trade does not have that API. `coinbase-api` does not pretend it does. Submit over REST, subscribe to `user` on `advTradeUserData` for live updates.

Bybit, from the SDK examples:

```js title="Imported example"
const { WebsocketAPIClient } = require("bybit-api");

const wsClient = new WebsocketAPIClient({
  key: process.env.API_KEY_COM,
  secret: process.env.API_SECRET_COM,
});

async function main() {
  const response = await wsClient.submitNewOrder({
category: "linear",
symbol: "BTCUSDT",
orderType: "Limit",
qty: "0.001",
side: "Buy",
price: "50000",
  });
  console.log(response);
}

main().catch(console.error);
```

### Is there a sandbox environment for testing Advanced Trade integrations? {#is-there-a-sandbox-environment-for-testing-advanced-trade-integrations}

No. The SDK marks Advanced Trade, App, Prime, and Commerce as `NoSandboxAvailable`. Exchange and International do have sandboxes. For Advanced Trade, use public product data, tiny live sizes, and keys with no transfer permission.

### How do I manage WebSocket reconnection in Node.js for Coinbase? {#how-do-i-manage-websocket-reconnection-in-node-js-for-coinbase}

`WebsocketClient` reconnects on close/error, emits `reconnect` then `reconnected`, and resubscribes. You still need to rebuild local books after a gap. Subscribe to `heartbeats` on the market-data socket if you want Coinbase's keepalive channel on top of the SDK ping/pong.

### Are Siebly SDKs compatible with TypeScript and coding agents? {#are-siebly-sdks-compatible-with-typescript-and-coding-agents}

Yes. They ship TypeScript types for requests and responses. Every Siebly exchange SDK on npm includes `llms.txt`. The [Siebly AI Prompt Framework and Skills](/ai) is the documented way to point an LLM at these packages.

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

- [Coinbase Advanced Trade Node.js Library: Production-Ready Implementation Guide](/blog/coinbase-advanced-trade-nodejs-library-production-ready-implementation-guide)
- [Integrating Coinbase Advanced Trade API with Node.js: A 2026 Engineering Guide](/blog/integrating-coinbase-advanced-trade-api-with-nodejs-a-2026-engineering-guide)
- [Implementing a Reliable Coinbase WebSocket Feed in Node.js](/blog/implementing-a-reliable-coinbase-websocket-feed-in-nodejs)


## 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)
- [Siebly AI Prompt Framework & Skills](/ai)
