Drıftstack docs
Docs

TypeScript quickstart

A five-minute path to a working TypeScript Driftstack session. For the multi-language overview see the combined quickstart.

Prerequisites

  • Node.js 18+ (Node 22 LTS recommended).
  • @driftstack/sdk 0.5.0 or newer. The examples on this page are written against it.
  • A paid plan: these steps use the AI agent, which the free trial does not include.
  • A ds_live_… customer API key. Mint one at app.driftstack.io/api-keys; the plaintext is shown once on creation.
  • The id of one of your saved proxies: every agent session goes out through a proxy you chose. See Find a proxy’s id.
  • A way to pay for the AI: your plan’s monthly AI credits, or your own Anthropic key. See Who pays for the AI.

1. Install

npm install @driftstack/sdk
# or: pnpm add @driftstack/sdk
# or: yarn add @driftstack/sdk

The package is dual-published (ESM + CommonJS via conditional exports) and ships full TypeScript types. Both import and require('@driftstack/sdk') work out of the box.

2. Configure the client

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

const client = new Driftstack({
  apiKey: process.env.DRIFTSTACK_API_KEY!,
  // Optional — defaults to https://api.driftstack.dev.
  // baseUrl: 'https://api.driftstack.dev',
});

The constructor doesn’t make any network calls. Authentication is deferred to the first request; an invalid key returns 401 on first use, not on construction.

3. Run your first session

An agent session is an iPhone Safari browser in the cloud that an AI drives for you: you send 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).

import { randomUUID } from 'node:crypto';

async function main() {
  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);
  }
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});

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.

4. Error handling

The SDK surfaces server-shape errors as typed exceptions. Match on err.status for HTTP semantics or err.type for the RFC 9457 Problem Details URL:

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

try {
  await client.agentSessions.create({ mode: 'ai', proxy_id: process.env.DRIFTSTACK_PROXY_ID! });
} catch (err) {
  if (err instanceof ProxyRequiredError) {
    // No proxy_id (or an empty one): nothing was created. Pass the id of one
    // of your saved proxies.
    console.error(err.detail);
  } else if (err instanceof DriftstackError) {
    if (err.status === 429 && err.type.endsWith('/concurrency-limit')) {
      // As many sessions open as your plan allows. Close one you created, or wait.
      console.error('concurrent cap reached:', err.detail);
    } else if (err.status === 402) {
      // The free trial has ended, or a subscription lapsed: the account keeps
      // its data, and sessions start again once it chooses a plan.
      console.error(err.detail);
    } else if (err.status === 401) {
      console.error('bad API key');
    } else {
      console.error('driftstack error:', err.type, err.detail);
    }
  } else {
    throw err;
  }
}

Errors also carry typed kind ('rate_limited', 'tier_limit', …) and extensions (e.g. RateLimitError.retryAfterSeconds) for fine-grained switching without string parsing.

5. Webhooks (optional)

Verify webhook signatures from the same SDK:

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

const ok = await verifyWebhookSignature({
  body: rawRequestBody,
  header: req.headers['x-driftstack-signature'] as string,
  secret: process.env.DRIFTSTACK_WEBHOOK_SECRET!,
});
if (!ok) return res.status(401).send('invalid signature');

During the 24h signing-secret rotation grace window the single x-driftstack-signature header carries both the new and old HMACs as two v1= entries (t=…,v1=<new>,v1=<old>) — see /webhooks/endpoints for the rotate-secret endpoint. verifyWebhookSignature already checks every v1= entry in that header, so the call above keeps verifying through a rotation with no extra arguments and your verifier won’t drop deliveries.

Next steps

  • Run AI tasks from your code — give the AI agent a task, read its answer, and handle questions, approvals, stops, errors and retries.
  • Session lifecycle reference — states, reconnect semantics.
  • Profile management — persistent profiles that survive across sessions.
  • Agent sessions — let an AI agent drive a session from plain-language instructions, with a live transcript stream and live video (the livekit field on the create response).
  • Who pays for the AI — the two ways to pay for the AI: your plan’s monthly AI credits, or your own Anthropic key.
  • Idempotency keys — Idempotency-Key is honoured on agent sessions, and NOT on POST /v1/sessions; retrying that one mints a second session.
  • Webhook event catalog — every event the platform can push.
  • Error catalogue — every problem-type you might see and how to react.
  • API versioning — what’s additive vs. major.

Stuck? Email [email protected] with your account id (acc_…) and the failing x-request-id.