Overview
coinbase-api is the Node.js package for Coinbase REST and WebSockets. Advanced Trade is one client in that package, CBAdvancedTradeClient, plus a shared WebsocketClient for the market and user streams. The client builds the JWT, signs the request, and exposes typed methods. Your application still decides how fast to call Coinbase, what to do when a call fails, and which key permissions are safe to grant.
The package docs explain how those endpoints show up as methods. The same npm package also includes clients for the Coinbase App, Exchange, International Exchange, Prime, and Commerce APIs. This guide stays on Advanced Trade.
Key Takeaways
- Install coinbase-api and use
CBAdvancedTradeClientfor Advanced Trade REST. UseWebsocketClientfor Advanced Trade market and user streams. - Advanced Trade auth is a JWT. Pass an ECDSA or ED25519 key as
apiKeyandapiSecret, or pass the downloaded CDP key JSON ascdpApiKey. The client detects the key type. - Public product calls need no API key. Account and order calls do.
- Place and cancel orders with REST methods such as
submitOrderandcancelOrders. The WebSocket client subscribes to channels. It does not place orders. - The client does not throttle requests and does not retry REST calls. WebSocket reconnect and resubscribe are handled by
WebsocketClient. useSandbox: trueswitches the Exchange and International clients. It does not point Advanced Trade at Coinbase's static sandbox.
When this SDK fits
Raw Advanced Trade calls repeat the same work: JWT signing, timestamps, request bodies, response parsing, and WebSocket connect, heartbeat, and resubscribe logic. coinbase-api already does that for the endpoints it implements.
Check the method list against the calls your app actually makes. The Advanced Trade client covers accounts, products, orders, fills, portfolios, futures, perpetuals, converts, payment methods, and the public market routes. The endpoint map lives in the package docs and in endpointFunctionList.md. If a route you need is missing there, do not assume a similarly named method exists.
TypeScript projects get request and response types with the package. JavaScript projects use the same methods. The build ships both ESM (import) and CommonJS (require).
What the client handles
The SDK handles request plumbing. For Advanced Trade that means JWT auth, key-type detection, timestamps, typed REST methods, and WebSocket connection tracking. WebsocketClient opens the socket it needs, sends heartbeats, reconnects after a drop, and resubscribes to the topics you already registered. Listen for open, update, reconnect, reconnected, close, response, and exception in your own code so you can log and react.
Your application handles safety. Store secrets outside the repo. Limit key permissions. Turn withdrawals off for automation keys. Pace requests yourself. Decide which errors are safe to retry. A dropped REST call is not retried by the client. Retrying submitOrder on a timeout can create a second order if the first one actually landed.
Coinbase defines the API. Accepted fields, product rules, auth requirements, and rate limits come from Coinbase. The SDK does not change them, and it does not slow calls down to stay under those limits.
Authentication
Advanced Trade and the Coinbase App API use the same JWT flow. Create a key in Coinbase API key management, then pass either the key name and private key, or the exported cdp_api_key.json object.
ECDSA secrets are PEM text, including the BEGIN EC PRIVATE KEY and END EC PRIVATE KEY lines. ED25519 secrets are the base64 private key string. You do not pass an API passphrase for Advanced Trade. Exchange, International, and Prime do use apiPassphrase, so do not reuse this constructor for those clients.
Load the values at runtime. The examples in the repo read API_KEY_NAME and API_PRIVATE_KEY.
Imported example
import { CBAdvancedTradeClient } from "coinbase-api";
const client = new CBAdvancedTradeClient({
apiKey: process.env.API_KEY_NAME,
apiSecret: process.env.API_PRIVATE_KEY,
});
The same values can be passed as one object:
Imported example
const client = new CBAdvancedTradeClient({
cdpApiKey: {
name: process.env.API_KEY_NAME,
privateKey: process.env.API_PRIVATE_KEY,
},
});
Rate limits and retries
Nothing in CBAdvancedTradeClient queues, delays, or drops calls to respect a rate limit. If Coinbase returns a limit error, your code sees the exception and has to decide what to do. Check the current Advanced Trade limit docs and put pacing in the application, around the client, so you can test it on its own.
REST methods are single attempts. There is no retry wrapper in the REST client. WebSocket reconnect is a separate path: the socket client will try to reconnect and then resubscribe. That does not replay a REST order.
submitOrder validates client_order_id. If you omit it, the client fills one in. Generated ids start with the prefix cbnode. If you pass your own id, use client.generateNewOrderId(), or the client will prepend that prefix and log a warning.
How to choose an integration approach
Pick the approach from the calls you need, then read how that library maps onto Coinbase's docs.
- Endpoint coverage.
CBAdvancedTradeClientmethods line up with Advanced Trade REST, includingsubmitOrder(POST /api/v3/brokerage/orders) andgetAccounts.WebsocketClientcovers the public market feed (advTradeMarketData) and the private user feed (advTradeUserData). - Docs. Trace a method to the Coinbase page for that route before you depend on a response field.
- Language. The package is JavaScript with TypeScript types, for Node. It also documents a webpack bundle for browser use. That bundle has smaller differences from the Node build, and the browser notes in the README are still thin, so treat browser use as something you verify yourself.
- Auth. Advanced Trade is JWT with ECDSA or ED25519, as shown above.
- Ownership. The library signs and sends. You own secrets, pacing, retries, and what a reconnect means for your order state.
Calling REST yourself means you maintain signing and request shapes. Coinbase's own samples and SDKs are worth reading against the same checklist. coinbase-api is the Siebly package that already implements the Advanced Trade clients described here. Other Siebly exchange packages (Binance, Bybit, OKX, and the rest) are separate npm modules with their own clients. They are listed on the SDK directory.
Build an Advanced Trade integration
Install the current package, then run one public call before you add keys.
Imported example
npm install coinbase-api
Read public market data
Public routes do not need a key. This follows examples/AdvancedTrade/Public/advanced-public-rest-all.ts.
Imported example
import { CBAdvancedTradeClient } from "coinbase-api";
// const { CBAdvancedTradeClient } = require('coinbase-api');
const client = new CBAdvancedTradeClient();
async function publicCalls() {
try {
const serverTime = await client.getServerTime();
console.log("Server Time: ", serverTime);
const publicProduct = await client.getPublicProduct({
product_id: "BTC-USD",
});
console.log("Public Product: ", publicProduct);
const productBook = await client.getPublicProductBook({
product_id: "BTC-USD",
limit: 10,
});
console.log("Public Product Book: ", productBook);
} catch (e) {
console.error("Error: ", e);
}
}
publicCalls();
The same file also calls getPublicProducts, getPublicProductCandles, and getPublicMarketTrades. Start with one of these and check the parsed object before you move on.
Read accounts
getAccounts is private. It needs the key from the authentication section. This follows examples/AdvancedTrade/Private/getAccounts.ts.
Imported example
import { CBAdvancedTradeClient } from "coinbase-api";
const client = new CBAdvancedTradeClient({
apiKey: process.env.API_KEY_NAME,
apiSecret: process.env.API_PRIVATE_KEY,
});
async function getAccounts() {
try {
const accounts = await client.getAccounts({ limit: 10 });
console.log("Accounts: ", accounts);
if (accounts.accounts.length > 0) {
const accountId = accounts.accounts[0].uuid;
const accountDetails = await client.getAccount({ account_id: accountId });
console.log("Account Details: ", accountDetails);
}
} catch (e) {
console.error("Get accounts error: ", e);
}
}
getAccounts();
getOrders and getOrder follow the same pattern in examples/AdvancedTrade/Private/getOrders.ts.
Submit an order
submitOrder is a live REST call to POST /api/v3/brokerage/orders. Run it only when you mean to trade, with a key that cannot withdraw, and with a size you are willing to send. This follows examples/AdvancedTrade/Private/submitOrderSpot.ts.
Imported example
import { CBAdvancedTradeClient } from "coinbase-api";
const client = new CBAdvancedTradeClient({
apiKey: process.env.API_KEY_NAME,
apiSecret: process.env.API_PRIVATE_KEY,
});
async function submitLimitOrder() {
try {
const limitOrder = await client.submitOrder({
product_id: "BTC-USDT",
order_configuration: {
limit_limit_gtc: {
base_size: "0.001",
limit_price: "50000.00",
},
},
side: "BUY",
client_order_id: client.generateNewOrderId(),
});
console.log("Limit Order Result: ", limitOrder);
} catch (e) {
console.error("Submit limit order error: ", e);
}
}
submitLimitOrder();
A market order uses the same method with order_configuration: { market_market_ioc: { base_size: '0.001' } }. Confirm the product id against getPublicProduct first. BTC-USD and BTC-USDT are different products, and the sample above uses the product id from the repo example.
There is no Advanced Trade WebSocket method for placing an order in this package. User-order updates arrive on the user stream after the REST call.
Subscribe to the market WebSocket
Public market data uses the ws key advTradeMarketData. No API key is required. The client connects to wss://advanced-trade-ws.coinbase.com when you subscribe. This follows examples/AdvancedTrade/WebSockets/publicWs.ts.
Imported example
import { WebsocketClient } from "coinbase-api";
const client = new WebsocketClient();
client.on("open", (data) => {
console.log("open: ", data?.wsKey);
});
client.on("update", (data) => {
console.info(new Date(), "data received: ", 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",
);
Other public topics in that example include heartbeats, candles, market_trades, status, ticker_batch, and level2. Pass a string, one object, or an array of objects as the first argument. The second argument is the ws key that selects the feed.
Private user streams use advTradeUserData and wss://advanced-trade-ws-user.coinbase.com. Put the same apiKey and apiSecret on WebsocketClient. Subscriptions on that ws key are signed with those credentials. The repo example subscribes to user and futures_balance_summary in examples/AdvancedTrade/WebSockets/privateWs.ts.
useSandbox does not give these Advanced Trade sockets a test host. The testnet entries in the client are NotAvailable.
About the Advanced Trade sandbox
Responses are fixed mocks in the production JSON shape. The published list is accounts, orders, and a handful of portfolio and perpetuals routes. A few error cases need an X-Sandbox request header.
useSandbox: true does not select that host for CBAdvancedTradeClient. In this package the Advanced Trade sandbox URL is the placeholder NoSandboxAvailable. Setting the flag sends traffic at that placeholder. The flag does work for CBExchangeClient (Exchange sandbox) and CBInternationalClient.
RestClientOptions also accepts baseUrl. Use the result to check response shape only. It will not show live matching, partial fills, or rate limits.
For a first integration check, the public product calls above are the path the examples actually use.
Keep the integration safe
Keep test keys and production keys in different runtime config. Prefer public product calls while you are wiring the client. Do not treat a sandbox mock, or a successful getPublicProduct, as proof that a live submitOrder will behave the same way.
Keep secrets out of source control, logs, screenshots, and chat transcripts. Grant only the permissions that workflow needs, and disable withdrawals on keys that place orders.
On the WebSocket side, the client owns the socket lifecycle. Your code should still handle exception and close, and it should rebuild any local order book from a fresh snapshot after reconnected. Do not keep applying deltas across a gap.
Before you widen the workflow:
- Secrets come from the environment or a secret manager, and the automation key cannot withdraw.
- The REST methods and WebSocket topics you call are in the current package and match the current Coinbase docs.
- Request pacing lives in your code and follows Coinbase's current limits.
- You have tests for bad input, auth failure, REST errors, and a socket drop followed by
reconnected.
The Coinbase JavaScript SDK page and the package README are the setup references. Explore Siebly.io for the other exchange packages.
Build on the methods the package actually ships
Confirm the REST methods and WebSocket topics you need, then install coinbase-api and call them as the examples do. Use CBAdvancedTradeClient for REST and WebsocketClient for streams. Keep Coinbase's docs next to you for field rules and limits. Pace requests in your own code, and keep order retries explicit.
Frequently Asked Questions
Does a Node.js SDK support Coinbase Advanced Trade?
Yes. The npm package is coinbase-api. Advanced Trade REST goes through CBAdvancedTradeClient. Streams go through WebsocketClient with the ws keys advTradeMarketData and advTradeUserData. Compare the method you want with Coinbase's Advanced Trade docs before you depend on a field.
How do I install it?
Imported example
npm install coinbase-api
Import CBAdvancedTradeClient or WebsocketClient from coinbase-api. CommonJS can require the same names. Types ship with the package. Avoid copying constructors from the Exchange or International examples. Those clients expect an API passphrase and, when you want it, useSandbox.
Does the Siebly Coinbase SDK handle rate limits for me?
No. coinbase-api does not delay or queue requests. Your application paces calls and handles limit errors. Coinbase's current docs are the reference for those limits. The same is true of the other Siebly exchange SDKs: they do not throttle for you. Some of them can surface rate-limit fields the exchange already returned. That is not the same as holding requests back.
Can I use WebSockets?
Yes, for streams. Construct WebsocketClient, subscribe with a topic and a ws key, and listen for update. Public market data uses advTradeMarketData. Private user data uses advTradeUserData and your API key. The client reconnects and resubscribes. Order placement stays on REST (submitOrder).
How should I store Coinbase API credentials?
Put API_KEY_NAME and API_PRIVATE_KEY in a secret manager or protected environment config. Keep them out of git, logs, and support tickets. Use a key that can only do what that process needs, with withdrawals disabled. ECDSA private keys include the PEM header and footer. ED25519 keys are the base64 secret. The client accepts either.
Is an SDK better than calling the API directly?
Use the SDK when you want the JWT signing, typed methods, and WebSocket reconnect that coinbase-api already implements, and when those methods cover your routes. Call the API yourself when you want to own every header and you already have that client code. Either way, Coinbase's docs define the API.
How can I test without placing a live order?
Call public methods such as getPublicProduct and getServerTime with new CBAdvancedTradeClient(). Subscribe to advTradeMarketData the same way, with no key. Coinbase's static sandbox is a separate host for mocked account and order JSON. useSandbox on this client does not select it. Exchange and International are the Coinbase products where that flag is wired up. Read the sandbox page before you point baseUrl anywhere, and do not treat mocks as live trading behavior.
Ready to try the client? Explore the Siebly Coinbase SDK and match it against the endpoints you need.
Related articles
Continue from here