TypeScript & JavaScript
The same SDK works in plain JavaScript and TypeScript. This page covers the shared client only—framework pages add automatic HTTP capture on top of this.
Read this page if you…
- Need one shared
ReplayStackClientfor workers, scripts, or manual logging. - Want to understand
captureEvent,captureException, and breadcrumbs before opening a framework guide.
Install
npm install @replaystack/sdk
# yarn add @replaystack/sdk
# pnpm add @replaystack/sdkTypical imports
The core client comes from @replaystack/sdk. Factory createReplayStackClient and new ReplayStackClient are equivalent (see runnable examples in Getting started). Framework middleware also lives at @replaystack/sdk/express, @replaystack/sdk/nextjs, and @replaystack/sdk/nestjs. Express middleware is also on the root entry; Nest and Next helpers use subpaths (v1.0.4+). Latest: @replaystack/sdk@1.0.7 on npm.
// Core client + manual capture (all frameworks)
import { createReplayStackClient, ReplayStackClient } from "@replaystack/sdk";
// Express middleware (also available from the root entry)
import { replayStackExpressMiddleware } from "@replaystack/sdk/express";
// Next.js route wrappers
import { withReplayStackNext, withReplayStackNextApi } from "@replaystack/sdk/nextjs";
// NestJS interceptor + exception filter (requires @nestjs/common in your app)
import {
createReplayStackNestInterceptor,
createReplayStackNestExceptionFilter,
} from "@replaystack/sdk/nestjs";Client options reference
Only apiKey is required. Everything else is optional—the SDK fills many values from environment variables when you do not pass them explicitly. For ReplayStack Cloud, you usually only need the key—omit endpoint to use the default host https://api.replaystack.co.
| Field | What it does | If you omit it | |
|---|---|---|---|
| apiKey | Required | Project key from the ReplayStack dashboard. Keep server-side only. | — |
| endpoint | Optional | API base URL (no /api/v1/... path). The SDK posts to /api/v1/ingest/events under this host. | REPLAYSTACK_ENDPOINT env, else https://api.replaystack.co |
| serviceName | Optional | Logical service name in the UI (filters, grouping). | REPLAYSTACK_SERVICE_NAME env, or set per event |
| environment | Optional | Label for where this process runs (production, staging, …). | NODE_ENV, else development |
| appVersion | Optional | Release or build version shown on events. | REPLAYSTACK_APP_VERSION / APP_VERSION env when not set on the client |
| commitHash | Optional | Git/deploy SHA for tying events to a revision. | REPLAYSTACK_COMMIT_HASH / COMMIT_HASH env when not set on the client |
| enabled | Optional | Turns all SDK sends off without removing code. | true unless REPLAYSTACK_ENABLED=false |
| timeoutMs | Optional | How long to wait on each ingest HTTP request. | 2500 (overridable via REPLAYSTACK_TIMEOUT_MS) |
| retries | Optional | Retries if the ingest request fails transiently. | 1 (REPLAYSTACK_RETRIES) |
| sampleRate | Optional | Random sample of events, 0–1. Use to reduce volume on success paths. | 1 (capture all) |
| captureSuccess | Optional | Whether successful HTTP-style events are sent (failures are still captured). | false — set true or REPLAYSTACK_CAPTURE_SUCCESS=true for 2xx traffic (examples often enable this) |
| captureLogs | Optional | Attach application log lines to events (e.g. error log on exceptions). | true — set false or REPLAYSTACK_CAPTURE_LOGS=false to disable |
| logLevel | Optional | Minimum log level stored when captureLogs is on. | error (REPLAYSTACK_LOG_LEVEL) |
| maxLogs | Optional | Max log lines kept per request context. | 50 |
| batchFlushIntervalMs | Optional | When > 0, buffer events and POST to /api/v1/ingest/bulk-events on an interval. | 0 (disabled; REPLAYSTACK_BATCH_FLUSH_INTERVAL_MS) |
| batchMaxEvents | Optional | Max events per bulk flush batch. | 20 (REPLAYSTACK_BATCH_MAX_EVENTS) |
| maxPayloadSizeBytes | Optional | Truncates very large JSON bodies/headers before send. | 512 KiB |
| maskFields | Optional | Extra field names to redact in payloads and headers (built-in sensitive list always applies). | built-in list always on (authorization, password, passwd, token, access_token, refresh_token, …) |
| ignoredPaths | Optional | URL paths to skip for client-level capture. Express middleware also merges its own defaults (/health, /metrics, /favicon.ico). | none |
| maxBreadcrumbs | Optional | Max breadcrumbs kept per request/client context. | 50 |
| fetchImpl | Optional | Inject fetch for tests or runtimes without global fetch. | globalThis.fetch |
| onError | Optional | Called if the SDK fails internally (network, parsing). Does not replace your app error handling. | none |
| offlineQueueMax | Optional | Max prepared events to keep in memory when ingest is down after retries. Oldest dropped when full. 0 = disable queueing. | 0 — set REPLAYSTACK_OFFLINE_QUEUE_MAX to buffer failed sends in RAM |
| flushIntervalMs | Optional | If > 0, periodically calls flush() to drain the offline queue when the API recovers. | 0 / disabled (REPLAYSTACK_FLUSH_INTERVAL_MS) |
| onQueueDrop | Optional | Callback when the offline queue exceeds offlineQueueMax and drops the oldest event. | none |
maskFields: optional extra JSON/header keys to redact. Passwords, tokens, cookies, and card fields are masked even when you omit this option. See Security & masking for the full built-in name list.
Lifecycle and reliability: call flush() to drain the in-memory queue after failed sends. close() stops new capture, cancels periodic flush, then drains. In Node, installReplayStackProcessGuards(client) from @replaystack/sdk registers optional hooks (unhandled rejection, uncaught exception, beforeExit) to flush best-effort—crash capture is not guaranteed.
Create one client per process
Build the client once (or inject a singleton in DI). Reuse it for all manual calls in that process. Comments in the snippet mark required vs optional fields—the table above lists every supported option.
import { createReplayStackClient } from "@replaystack/sdk";
const replayStack = createReplayStackClient({
// Required — project key from the dashboard (never expose to the browser).
apiKey: process.env.REPLAYSTACK_API_KEY!,
// Optional — API base URL; can rely on REPLAYSTACK_ENDPOINT instead.
endpoint: process.env.REPLAYSTACK_ENDPOINT!,
// Optional — service label in the UI; env REPLAYSTACK_SERVICE_NAME also works at send time.
serviceName: process.env.REPLAYSTACK_SERVICE_NAME || "order-service",
// Optional — defaults to NODE_ENV.
environment: process.env.NODE_ENV || "development",
// Optional — release metadata (env fallbacks apply if omitted).
appVersion: process.env.APP_VERSION,
commitHash: process.env.COMMIT_HASH,
// Optional — skip these paths for client-level capture.
ignoredPaths: ["/health", "/metrics"],
// Optional — 1 = all events; use a lower number to sample.
sampleRate: 1,
});Manual event
Use for queues, cron, webhooks, or any non-HTTP workflow you want in the dashboard.
await replayStack.captureEvent({
eventType: "queue",
endpoint: "send-email-job",
status: "failed",
errorMessage: "SMTP timeout",
requestPayload: { userId: "123" },
});Manual exception
Inside catch, record the error and rethrow if you need existing behavior.
try {
await chargeCard(order);
} catch (error) {
await replayStack.captureException(error, {
eventType: "custom",
endpoint: "process-payment",
requestPayload: { orderId: order.id },
});
throw error;
}Breadcrumbs
Optional short messages that show the business path before an error:
replayStack.addBreadcrumb("Order validated");
replayStack.addBreadcrumb("Charging card");What HTTP adapters add
- Method, route, request/response bodies, status, and duration.
- Exception name, message, stack, and parsed frames when something throws.
- Metadata such as
commitHash,environment, andappVersion.
sampleRate only to thin out successful traffic when you have high volume.