Skip to main content

TypeScript SDK quickstart

The @driftstack/sdk package wraps the same REST surface as the curl quickstart, with end-to-end types generated from the OpenAPI spec. If you're already in a TS codebase, this is the recommended way to call Driftstack.

SDK automation needs a ds_live_… customer API key. Every plan includes the API, the free trial too.

1. Install

# bun
bun add @driftstack/sdk

# npm
npm install @driftstack/sdk

# pnpm
pnpm add @driftstack/sdk

Node ≥ 18 is supported. The package is dual-published (ESM + CommonJS via conditional exports); both import and require('@driftstack/sdk') work out of the box.

2. Construct the client

import { Driftstack } from '@driftstack/sdk';

const client = new Driftstack({
  apiKey: process.env.DRIFTSTACK_API_KEY!,
  // baseUrl defaults to https://api.driftstack.dev; override for
  // self-hosted deployments or staging.
});

The constructor does not make any network calls. Reuse one client across your process — it is internally pooled and safe for concurrent use.

3. Run your first agent session

An agent session is an iPhone Safari browser in the cloud that an AI drives for you: your code sends a task in plain words, and the agent plans the taps and page loads, runs them, and answers. Every agent session goes out through one of your saved proxies, so the create names its id (proxy_id). You will need:

import { randomUUID } from 'node:crypto';

const agent = await client.agentSessions.create({
  mode: 'ai',
  proxy_id: process.env.DRIFTSTACK_PROXY_ID!,
});
try {
  // Wait up to two minutes for its browser: status is 'active' from the
  // start, so read ready.
  for (let i = 0; i < 60; i++) {
    const s = await client.agentSessions.get(agent.id);
    if (s.status === 'closed') throw new Error('The session did not start: ' + s.closed_reason);
    if (s.ready !== false) break;
    await new Promise((resolve) => setTimeout(resolve, 2_000));
  }
  const reply = await client.agentSessions.message(
    agent.id,
    'Open https://example.com and tell me the page title.',
    { idempotencyKey: randomUUID() },
  );
  if (reply.kind === 'plan-executed') console.log(reply.answer ?? reply.results);
  else console.log(reply.kind, reply);
} finally {
  // Always close it: an open session counts against your plan's
  // concurrent-session limit.
  await client.agentSessions.close(agent.id);
}

4. What happened

The guide Run AI tasks from your code covers the rest a program needs: answering the agent's questions, approving a payment it held, stopping a task that runs too long, safe retries, and limits.

5. Paginate over your agent sessions

for await (const s of client.agentSessions.iterate({ limit: 50 })) {
  if (s.status === 'closed') console.log(s.id, s.closed_reason);
}

iterate walks cursor pages transparently, newest first, and stops when the server returns next_cursor: null. The single-page form is client.agentSessions.list({ limit, cursor }). From 0.6.0 (not published yet), both take status (for example { status: 'open' }) to list only the sessions with that status; iterate keeps it on every page.

Error handling

Every SDK method throws a typed DriftstackError on non-2xx responses. The error carries kind (discriminator, narrow with ===), status, type (the RFC 9457 URI), detail, and any extension fields from the problem response. Switch on kind for clean type-narrowing:

import { DriftstackError } from '@driftstack/sdk';

try {
  await client.agentSessions.create({ mode: 'ai', proxy_id: process.env.DRIFTSTACK_PROXY_ID! });
} catch (err) {
  if (err instanceof DriftstackError && err.kind === 'proxy_required') {
    // ProxyRequiredError — no proxy_id, so nothing was created
  } else if (err instanceof DriftstackError && err.kind === 'rate_limited') {
    // RateLimitError subclass — `err.retryAfterSeconds` is set
  } else {
    throw err;
  }
}

Driving each step yourself

client.sessions is the direct session API: your code drives each step itself with navigate, interact, wait and capture instead of giving an AI a task. On hosted Driftstack only agent sessions load pages, so use client.agentSessions for real browsing. See the Sessions reference.

Where to go next

Need help?

[email protected]. Reply times follow your plan's support on the pricing page: a 48-hour reply target on Starter and Pro.