@driftstack/sdk
v0.1.6
Published
Official TypeScript SDK for the Driftstack API
Maintainers
Readme
@driftstack/sdk
Official TypeScript SDK for the Driftstack API.
Status: pre-1.0. Stable surface for the API contract; the SDK API may shift before 1.0. Don't pin against an exact version yet.
Install
npm install @driftstack/sdk
# or
pnpm add @driftstack/sdk
# or
yarn add @driftstack/sdkRequires Node.js ≥ 18 (uses native fetch). Works in any modern runtime that exposes fetch and node:crypto.
Quickstart
import { Driftstack } from '@driftstack/sdk';
const client = new Driftstack({ apiKey: process.env.DRIFTSTACK_API_KEY! });
const session = await client.sessions.create({ label: 'login flow' });
await client.sessions.navigate(session.id, { url: 'https://example.com' });
const screenshot = await client.sessions.capture(session.id, { kind: 'screenshot' });
await client.sessions.destroy(session.id);Configuration
new Driftstack({
apiKey: 'ds_live_…', // required
baseUrl: 'https://api.driftstack.dev', // optional override
timeoutMs: 30_000, // per-request timeout
retry: {
// retry policy (defaults shown)
maxAttempts: 3,
initialDelayMs: 250,
maxDelayMs: 8_000,
},
});Resources
client.sessions.create(body?)
client.sessions.list(query?)
client.sessions.navigate(id, body)
client.sessions.interact(id, body)
client.sessions.wait(id, body)
client.sessions.getState(id)
client.sessions.capture(id, body)
client.sessions.destroy(id)
client.apiKeys.create(body) // requires admin scope
client.apiKeys.list()
client.apiKeys.revoke(id) // requires admin scope
client.usage.current()Every method is fully typed against the public OpenAPI 3.1 contract sourced from @driftstack/api-types. Hover anywhere in your editor to see the request and response shapes.
Errors
Every error thrown by the SDK extends DriftstackError. Catch the base class to handle anything, or specific subclasses for granular logic:
import {
Driftstack,
RateLimitError,
ConcurrencyLimitError,
ValidationError,
DriftstackError,
} from '@driftstack/sdk';
try {
const session = await client.sessions.create();
// ...
} catch (err) {
if (err instanceof RateLimitError) {
console.warn(`Rate limited; retry after ${err.retryAfterSeconds}s`);
} else if (err instanceof ConcurrencyLimitError) {
console.warn(`At ${err.currentSessions}/${err.limit} concurrent sessions`);
} else if (err instanceof ValidationError) {
console.error('Validation failed:', err.issues);
} else if (err instanceof DriftstackError) {
console.error(`API error ${err.status}: ${err.title}`, err.detail);
} else {
throw err;
}
}Retry behaviour
By default the SDK retries automatically on:
- network failures (
TransportError) - 5xx server errors
- 429 rate-limit responses (honours
Retry-Afterheader /retry_after_secondsbody field)
It does not retry 4xx responses other than 429. Backoff is exponential with full jitter, capped at maxDelayMs. Set retry: { maxAttempts: 0 } to disable retries entirely.
Webhook signature verification
When you wire up Driftstack webhooks, verify each delivery before processing:
import { verifyWebhookSignature } from '@driftstack/sdk';
app.post('/driftstack-webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const ok = await verifyWebhookSignature({
body: req.body, // raw bytes — DO NOT use a parsed body
header: req.headers['x-driftstack-signature'],
secret: process.env.DRIFTSTACK_WEBHOOK_SECRET!,
});
if (!ok) return res.status(401).end();
// ... process the event ...
res.status(204).end();
});The verifier uses HMAC-SHA256 with constant-time comparison and rejects timestamps older than 5 minutes (configurable via toleranceSec). It's browser-isomorphic — verifyWebhookSignature works the same way in Node 20+, every modern browser, Tauri WebViews, Cloudflare Workers, Deno, and Bun (uses Web Crypto API under the hood, hence the await).
Examples
See examples/ for complete runnable demos:
quickstart.ts— happiest path, end-to-enderror-handling.ts— every documented error classrate-limit-handling.ts— explicit retry-after honouring on top of the built-in retry
License
MIT
