Skip to main content
Use @0xinsider/sdk in a Node.js application to call the API, paginate lists, read the event stream, and verify webhooks. It includes TypeScript declarations and typed errors. The source repository contains the client and examples.

Install

You need Node.js 18 or newer. The package is ESM only and has no runtime dependencies. For local SDK development, clone the source repository, run npm ci && npm run build, and install that directory from your project.

Make a request without a key

OxinsiderApiClient.sandbox() returns example data from the sandbox. It needs no credential and stores nothing. Successful JSON responses carry meta.sandbox: true.
Use sandbox_status to request a documented error example. Because that parameter is specific to the sandbox, the example uses the low-level call<T>() form. Live keys are refused in sandbox mode; streams and file downloads return 400.

Switch to live data

Set OXINSIDER_API_KEY in your environment and pass it as apiKey. Live data requires an active Pro or Max subscription; see Authentication.
The default origin is https://api.0xinsider.com. A custom baseUrl keeps its path prefix and must use HTTPS, except for a loopback development host. Public operations can be called without a key; protected operations reject a missing key before sending the request.

Read a pick by stable ID

Published SDK 0.15.0 includes getPickOfTheDayLedgerEntry(pickId) for the public ledger entry route. Install that version or newer to use the helper; SDK 0.14.0 does not include it.
Keep pick_id as a decimal string. This request needs no key. Read state before accessing disclosure fields: a live sealed entry withholds the side, payload, and nonce; an opened entry includes its canonical payload and nonce. For committed entries, read commitment_version to select the proof format. Version 1 keeps the original payload with pick_rank; version 2 uses pick_id and integer version: 2. Use is_free_selection to determine access, rather than deriving it from publication_order.

Handle tier-dependent pick fields

Treat a current response’s pick fields, archive matchup, and archive category as optional. An unauthorized pending row intentionally omits identifying fields; it is not an incomplete game you should enrich through another endpoint. Public API scheduled_picks contains only entitled rows and retains its release and kickoff clocks; unauthorized scheduled ranks appear in locked_picks. Read state and locked_picks before assuming a current-pick response contains selections. Public sealed ledger entries omit kickoff, while opened proof payloads retain the kickoff needed for verification. Use SDK declarations generated from the updated schema when that release is available; this change does not announce a new npm version.

Pass typed parameters

Each method knows its operation’s path parameters, query parameters, body, and response. You do not need to supply a response type. A query the endpoint does not support, or a missing path parameter, produces a TypeScript error. The remaining snippets use the live client created above. Pass transport settings after the method’s parameters:
call, list, paginate, paginatePages, and collect are typed when you pass a literal operation ID. Their low-level form accepts an operation selected at runtime or an explicit type argument; you then own the asserted response shape. Use listSuspiciousTrades() and getSuspiciousTrade() for flagged trades. The listInsiderRadar() and getInsiderRadarFlag() methods remain as deprecated aliases. Their older event types keep the "insider_radar_flag_raised" discriminant for existing subscribers.

Understand timeouts and retries

The client does not retry ordinary request timeouts, 400, 401, 402, 403, 404, 409, or 500. A write without safe replay support is sent once.

Keep money values exact

Trader and position responses can include an exact block containing decimal strings. Use them for arithmetic when available. Parse the string directly with a decimal library; converting through Number first can lose precision.
Each value includes unit, scale, and basis. The block or one of its fields can be absent when the source is unavailable. Report that absence instead of substituting zero.

Read up to 25 traders at once

batchGetTraders() calls Batch traders. It returns one item per input in the same order, including duplicates.
Check each item’s status. An ok item contains data; an error item contains its own error. One unknown identifier does not fail the other inputs. meta.request_cost measures batch item units. It does not measure the number of HTTP requests.

Read every page

paginate() yields each item and follows next_cursor. paginatePages() yields whole response envelopes when you also need metadata.
A missing or repeated continuation cursor raises PaginationError before the page is yielded. Its reason is missing_cursor or repeated_cursor, and it includes the page that failed validation. Use maxPages to stop at a positive page count, signal to cancel, and progress to retain the last paging position. A limit you supplied does not mean you reached the end of the list. paginationResumePoint() also returns a continuation point from a paging failure. Keep filters unchanged during a traversal. See Pagination for expired cursors.

Reuse a cached response

The client copies a response’s ETag header to meta.etag. Send it back as If-None-Match to check whether your cached body is current.
A 304 returns a not_modified result with data: null. Keep your cached body; do not replace it with null.

Handle errors

API error statuses raise a subclass of OxinsiderApiError. The client selects a class by error.reason first, then error.code. A 304 is handled separately as described above. Errors expose status, code, retryAt, error, meta, requestId, and the raw body. Errors with retry timing also expose retryAfterSeconds. The client’s automatic retries finish before your code catches the final error. Read the API’s reason from err.error.reason. err.reason is only populated for subclasses tied to a specific reason, so it may be null even when the API body includes a reason.
Check monthly_quota_exceeded before scheduling another rate-limit retry. Its reset can be next month. A future retryAt, including a pick release time, belongs in your scheduler rather than a long-running sleep.

Make a safely repeatable webhook write

These 8 operations accept idempotencyKey: createWebhook, updateWebhook, deleteWebhook, rotateWebhookSecret, prepareWebhookSecret, activateWebhookSecret, retireWebhookSecret, and redeliverWebhookDelivery.
Keep the key and body unchanged when retrying the same operation. The client rejects an idempotency key on an unsupported operation. After a timeout, the write may have succeeded; replay the same key and body or read the resource to check. The first 3 operations and redeliverWebhookDelivery have convenience methods. Use client.call() for secret rotation operations. Webhooks explains setup, verification, and rotation.

Read the stream

The helpers support Last-Event-ID and the stream’s event, condition_id, and min_grade filters. Stream connections have no total request deadline. Supply signal to cancel when your task ends; this example reads for at most 30 seconds:
A malformed frame, a non-SSE success response, or a frame larger than maxFrameBytes (1 MiB by default) raises StreamProtocolError. Its lastSeq identifies the last valid frame; automatic reconnection does not retry a protocol failure. A Retry-After longer than maxRetryAfterMs (60 seconds by default) raises StreamRetryDeferredError with retryAt and lastSeq. Schedule reconnection for that time.

Save a checkpoint after processing

consumeStreamCheckpointed() distinguishes the last received frame (cursor) from the last completed frame (checkpoint). It advances the checkpoint only after both onEvent and onCheckpoint resolve. If a handler fails, the connection closes and reconnects from the checkpoint. After maxHandlerRetries consecutive failures on one sequence (3 by default), it raises StreamHandlerFailedError with the sequence and recovery position. Delivery can repeat, so deduplicate on seq or make your side effect idempotent. onResync is awaited before a refreshed state is committed. See Stream for what a resync means.

Verify webhook signatures

verifySignature(input) checks x-0xinsider-signature against the raw request body. It uses a constant-time comparison and a 300-second timestamp tolerance, and accepts any valid signature candidate during staged secret rotation. It returns false for an invalid signature or timestamp. An empty secret or invalid toleranceSeconds throws instead. parseWebhookEvent(body) then parses the typed event; see Webhooks.

Finish or cancel downloads

downloadTraderExport and downloadWhaleDataset return streaming download objects. Consume response.body to completion or cancel it when you stop reading. If a helper fails before it can return the object, it cancels the body and waits up to 2 seconds for cleanup. The original failure remains the main error; cleanup rejection or timeout is retained in cause. An AggregateError preserves both when the original thrown value cannot carry a cause. A cleanup timeout means completion is unknown. Do not report the file as downloaded unless you finished reading it and performed the required integrity checks.

Limits

  • The SDK does not place Polymarket orders or hold a wallet key.
  • It can manage your 0xinsider webhooks and exports.
  • Missing values remain missing. Keep numeric precision until display.
  • Long Retry-After and retryAt waits need application scheduling.