JavaScript
The @chartdeck/api package - ESM with types, namespaces, pagination, retries, errors, the stream helper and webhook verification.
npm install @chartdeck/apiNode 18 or newer (Node 22 for the built-in WebSocket; on 18 and 20 pass the ws package's class as WebSocket), ESM with TypeScript types, no runtime dependencies. It refuses to run in a browser: keys belong on servers.
#Client
import { ChartDeck } from '@chartdeck/api';
const cd = new ChartDeck(); // the key from CHARTDECK_API_KEY
const cd2 = new ChartDeck({ apiKey: 'cdk_...', timeoutMs: 30000, maxRetries: 3 });Methods are grouped like the API (cd.market, cd.calendar, cd.strata, cd.flow, ...). Path parameters come first, then the body for writes, then an object of query parameters (plus idempotencyKey and signal). Date objects work for times.
const r = await cd.market.candles({ venue: 'binance', symbol: 'BTCUSDT', res: '60', limit: 500 });
r.data; r.meta.attribution; r.rateLimit.remaining; r.requestId;
await cd.call('getCandles', { venue: 'binance', symbol: 'BTCUSDT', res: '60' }); // by operationId#Pagination
for await (const bar of cd.market.candles.iterate({ venue: 'binance', symbol: 'BTCUSDT', res: '60', maxItems: 5000 })) { /* rows */ }
for await (const page of cd.market.candles.pages({ venue: 'binance', symbol: 'BTCUSDT', res: '60' })) { /* whole pages */ }#Retries and errors
The same rules as the Python client: 429 rate_limited, 502, 503, 504 and network errors are retried with backoff and jitter, honouring Retry-After; the monthly quota and other 4xx are not; writes carry an automatic Idempotency-Key. Errors are ChartDeckError subclasses (AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, InvalidRequestError, RateLimitError, ServiceUnavailableError, APIConnectionError) with status, code, requestId, retryAfter, details.
#Stream
const s = cd.stream({ channels: ['trades:binance:BTCUSDT', 'calendar:US'] });
s.on('notice', (m) => console.log('notice', m.code));
for await (const frame of s) console.log(frame.ch, frame.type, frame.data);s.subscribe([...]), s.unsubscribe([...]), s.close(). With the built-in WebSocket the key goes in the first message; pass WebSocket (a class taking headers) to send it on the upgrade instead. Reconnect, re-subscribe, resume and replay dedupe as in Python.
#Webhooks
import { constructEvent, verifyChartDeckSignature } from '@chartdeck/api';
verifyChartDeckSignature(rawBody, req.headers['chartdeck-signature'], secret); // true / false
const event = constructEvent(rawBody, req.headers['chartdeck-signature'], secret); // or throws