GeminiGemini
SandboxGet API key
  • Crypto Trading
  • Prediction Markets
  • SDKs & Tools
Changelog
Gemini Crypto Exchange LogoGemini Crypto Exchange Logo

© 2026 Gemini Space Station, Inc.

Overview
TypeScript SDK
    QuickstartAuthenticationWebSocketError HandlingPatterns & Recipes
    API Reference
    Deep Dives
TypeScript SDK

TypeScript SDK — Patterns & Recipes

Common patterns for timeouts, cancellation, pagination, heartbeat, and advanced client configuration.

Timeouts and cancellation

Every SDK method accepts timeoutMs and signal for deadline control:

Code
// Per-request timeout const symbols = await client.marketData.listSymbols({ timeoutMs: 5_000, }); // Cancellation via AbortController const controller = new AbortController(); const events = client.predictions.listEvents( { status: ["active"] }, { signal: controller.signal }, ); // Cancel from elsewhere controller.abort();

Set a default timeout for all operations on the client:

Code
const client = await createClient({ auth, timeoutMs: 10_000, // 10s default for all REST and WebSocket waits });

WebSocket stream listeners also support signal-based cleanup:

Code
const trades = client.websocket.trades("BTCUSD"); const controller = new AbortController(); trades.on("message", (trade) => { console.log(trade); }, { signal: controller.signal }); // Later: remove the listener without manually calling off() controller.abort();

Pagination

List endpoints that return many results use offset pagination. The SDK provides an async generator that walks pages automatically:

Code
import { HttpTransport, HmacAuth } from "gemini-markets/server"; const transport = new HttpTransport({ env: "sandbox", auth: new HmacAuth({ apiKey, apiSecret }), }); // Walk prediction market positions, 100 per page, up to 500 total for await (const position of transport.paginate({ method: "POST", path: "/v1/prediction-markets/positions", limit: 100, maxItems: 500, itemsKey: "positions", // response is { positions, total }, not a bare array parameterLocation: "query", // limit/offset go as query params, not in signed payload })) { console.log(position); }

Deduplication

Offset pagination is not snapshot-consistent — records can shift between pages while you're iterating. Use dedupeKey to fail loudly if the same record appears twice:

Code
for await (const position of transport.paginate({ method: "POST", path: "/v1/prediction-markets/positions", limit: 100, itemsKey: "positions", parameterLocation: "query", dedupeKey: (item: unknown) => { const pos = item as Record<string, unknown>; return `${pos.instrumentId}:${pos.outcome}`; // instrumentId alone is not unique — YES and NO positions share the same ID }, })) { // Throws SdkError if a duplicate instrumentId:outcome pair is seen }

Heartbeat

Keep a session alive with an explicit heartbeat. The heartbeat is stopped by default — you control its lifecycle:

Code
const heartbeat = client.createHeartbeat({ intervalMs: 15_000, // default onError: (err) => console.error("Heartbeat failed:", err), }); heartbeat.start(); // Later heartbeat.stop();

The heartbeat sends a POST /v1/heartbeat request at the configured interval. It requires an authenticated client (HMAC or OAuth).

File responses

Some endpoints return binary files (XLSX, CSV) instead of JSON:

Code
const report = await client.marketData.getFundingAmountReportFile({ symbol: "BTCGUSDPERP", }); // report.bytes: Uint8Array — the raw file content // report.contentType: string | undefined (e.g. "text/csv" or XLSX MIME type) // report.contentDisposition: string | undefined (Content-Disposition header) // Write to disk (Node.js) import { writeFileSync } from "node:fs"; const ext = report.contentType.includes("csv") ? "csv" : "xlsx"; writeFileSync(`funding-report.${ext}`, report.bytes);

Prediction markets — terms acceptance

Prediction market order placement requires accepting the current terms. The SDK enforces this:

Code
// Check terms status const terms = await client.predictions.getPredictionMarketsTermsStatus(); if (!terms.hasAcceptedLatest) { // Show terms to the user, get explicit consent, then: await client.predictions.acceptTerms(); } // Now orders will work await client.predictions.placeOrder({ /* ... */ });

If you skip this, the SDK throws AcceptTermsRequired.

Advanced client options

The full set of options available on createClient():

Code
const client = await createClient({ // Environment env: "sandbox", // "sandbox" | "production" // Authentication auth: new HmacAuth({ apiKey, apiSecret }), // Timeouts and retries timeoutMs: 30_000, // default: 30s maxRetries: 5, // default: 5 (safe reads only) backoff: { baseMs: 500, // initial backoff (default: 500) capMs: 30_000, // maximum backoff factor: 2, // exponential factor }, // WebSocket skipWsInit: false, // true to skip ws preloading (REST-only) webSocketFactory: customFactory, // custom socket factory webSocketLiveness: { intervalMs: 30_000, // liveness check interval timeoutMs: 5_000, // liveness check timeout }, webSocketMaxMessageSizeBytes: 1_048_576, // 1MB frame limit // Custom fetch (for proxies, instrumentation, or testing) fetch: customFetchImpl, // Observability logger: new ConsoleLogger({ minLevel: "debug" }), onDiagnostic: (event) => telemetry.record(event), });

Runtime compatibility

The SDK runs on any runtime with Web Crypto and standard fetch:

RuntimeBrowser entryServer entryNotes
Node.js 22+YesYesFull support
Node.js 18–21YesYesPartial — no lossless JSON (throws on responses containing unsafe integers)
BunYesYesPartial — no lossless JSON (Bun lacks JSON.parse source access as of v1.x)
DenoYesYesPartial — no lossless JSON (Deno lacks JSON.parse source access as of v2.x)
Cloudflare WorkersYesNoNo ws package — browser entry only; no lossless JSON
BrowsersYesNoNo API secrets in client code; no lossless JSON

The server entry requires the ws peer dependency for authenticated WebSocket connections:

TerminalCode
npm install ws

ws is optional — if you only use REST endpoints with skipWsInit: true, you don't need it.

Closing the client

Always close the client when done to release WebSocket connections:

Code
const client = await createClient({ auth }); try { // ... use the client } finally { client.close(); }

close() shuts down all active WebSocket streams and the shared session. It does not cancel in-flight REST requests.

What's next

  • API Reference — all 105 operations with code examples
  • WebSocket Reference — streams, methods, and wire format
  • Deep dives — order book reconstruction, RFQ, sessions, transport internals
Last modified on August 14, 2026
Error HandlingAPI Reference
On this page
  • Timeouts and cancellation
  • Pagination
    • Deduplication
  • Heartbeat
  • File responses
  • Prediction markets — terms acceptance
  • Advanced client options
  • Runtime compatibility
  • Closing the client
  • What's next
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript