> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boat.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript and JavaScript SDK

> Install, configure, and use the @boatdev/sdk npm package.

<video controls playsInline preload="metadata" poster="/videos/sdks-typescript.jpg" src="https://mintcdn.com/ariana-1e97e6c3/KkeC9MhSefNUGJb6/videos/sdks-typescript.mp4?fit=max&auto=format&n=KkeC9MhSefNUGJb6&q=85&s=d169b8fdda983ec62465cf35c30ed4aa" className="w-full aspect-video rounded-xl" data-path="videos/sdks-typescript.mp4" />

Install the npm package:

```bash theme={null}
npm install @boatdev/sdk
```

Import `BoatApi`, configure auth, and call methods like `sandbox.create`, `sandbox.prompt`, and `sandbox.events`.

## Configure

```ts theme={null}
import { BoatApi, Configuration, waitUntilReady, waitForPrompt } from "@boatdev/sdk";

const sandbox = new BoatApi(new Configuration({
  basePath: process.env.BOAT_BASE_URL ?? "https://boat.dev/api/v1",
  accessToken: process.env.BOAT_API_KEY ?? (() => {
    throw new Error("Set BOAT_API_KEY from the Boat dashboard API keys tab.");
  })(),
}));
```

For TypeScript projects, use modern Node resolution and DOM fetch types:

```json theme={null}
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ES2022", "DOM"],
    "types": ["node"],
    "strict": true
  }
}
```

Node 18+ provides `fetch`. Older runtimes need a fetch polyfill. For ESM examples, set `"type": "module"` in `package.json`; CommonJS projects can use the `require` example below.

## Create, prompt, and clean up

```ts theme={null}
import { BoatApi, Configuration } from "@boatdev/sdk";

const sandbox = new BoatApi(new Configuration({
  basePath: process.env.BOAT_BASE_URL ?? "https://boat.dev/api/v1",
  accessToken: process.env.BOAT_API_KEY ?? (() => {
    throw new Error("Set BOAT_API_KEY from the Boat dashboard API keys tab.");
  })(),
}));

async function main() {
  let sandboxId: string | undefined;

  try {
    const created = await sandbox.create({ ttlSeconds: 1800 });
    sandboxId = created.sandbox.id;

    await sandbox.update({
      sandboxId,
      name: "sdk-demo",
    });

    await waitUntilReady(sandbox, sandboxId);

    const queued = await sandbox.prompt({
      sandboxId,
      provider: "codex",
      prompt: "Inspect the repository and summarize the test command.",
    });

    const run = await waitForPrompt(sandbox, sandboxId, queued.promptId);
    console.log(run.status);

    const events = await sandbox.events({ sandboxId, limit: 50, type: "prompt,response" });
    console.log(events.events);
  } finally {
    if (sandboxId) await sandbox.stop({ sandboxId });
  }
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

<Note>
  Use `ttlSeconds` when creating a sandbox. Set a friendly name afterward with `sandbox.update`.
</Note>

## Machine size

Pass `type` to create a bigger Boat. `large` consumes machine time at 2x, `small` at half rate. A
fork inherits the source sandbox's type, and passing `type` to `resume` or `fork` moves a sandbox between
sizes.

```ts theme={null}
const created = await sandbox.create({ type: "large", ttlSeconds: 3600 });

const info = await sandbox.get({ sandboxId: created.sandbox.id });
console.log(info.sandbox.type, info.sandbox.vcpu, info.sandbox.memoryGB);
```

See [Machine Capabilities](/machines) and [Pricing](/pricing).

## Per-sandbox environment variables

Pass `env` to inject variables into a single sandbox, on top of your account-level secrets
(per-sandbox values win on name conflicts). At most 100 variables, 64KB total.

```ts theme={null}
const created = await sandbox.create({
  ttlSeconds: 3600,
  env: { DATABASE_URL: "postgres://user:pass@host:5432/app", FEATURE_FLAG: "1" },
});
```

Forked Sandboxes inherit the source sandbox's `env` unless the fork supplies its own.

## No-env sandboxes

When you hand a sandbox to your own end users, create it with `noEnv: true` so none of your
account secrets reach it. Model keys, GitHub token, dashboard environment variables, SSH
identity, and secret files are all withheld. SSH, desktop, snapshots, public URLs, and
forks still work. A fork of a no-env Boat is always no-env and cannot be downgraded.

```ts theme={null}
const created = await sandbox.create({ ttlSeconds: 1800, noEnv: true });

await sandbox.resume({
  sandboxId,
  noEnv: true,
});

const forked = await sandbox.fork({
  sandboxId,
  noEnv: true,
});
```

## CommonJS

```js theme={null}
const { BoatApi, Configuration } = require("@boatdev/sdk");

const sandbox = new BoatApi(new Configuration({
  basePath: process.env.BOAT_BASE_URL || "https://boat.dev/api/v1",
  accessToken: process.env.BOAT_API_KEY,
}));
```

## Methods

All methods are called on `BoatApi` with one object. For a method that takes a request body, put the body's fields (`...body` below) directly in that object next to the path and query parameters: `saveNamedSnapshot({ sandboxId, name })`, `fork({ sandboxId, type: "small" })`. The wrapped form the SDK has always accepted, `fork({ sandboxId, forkRequest: { type: "small" } })`, still works and sends the same request. The flat form needs @boatdev/sdk 1.1.0 or later; on 1.0.x, use the wrapped form.

| Method | Arguments | Returns | Use |
| - | - | - | - |
| `me()` | none | `Promise<MeResponse>` | Get the authenticated Boat account user. |
| `limits()` | none | `Promise<LimitsResponse>` | Check whether the account can create or operate sandboxes before starting work. |
| `repos({ sync, limit, cursor, sort, q, selected }?)` | optional sync, pagination, search, and selected-only filters | `Promise<ReposResponse>` | List GitHub installations, repositories, and selected repositories. |
| `selectRepo({ ...body })` | `repositoryId`, optional `baseBranch` | `Promise<RepoSelectionResponse>` | Select a repository for future sandboxes. Use `databaseId` from `repos()` as `repositoryId`. |
| `apiKeys()` | none | `Promise<ApiKeysResponse>` | List API key metadata, including 30-day request totals and live resource counts. Raw secrets are not returned. |
| `secrets()` | none | `Promise<SecretsResponse>` | Read the current environment variables and secret files configured for sandboxes. |
| `updateSecrets({ ...body })` | `envContents`, `secretFiles` | `Promise<SecretsResponse>` | Replace the complete secret setup. Send every env var and file that should remain. |
| `sandboxes({ limit, cursor, sort, state }?)` | optional pagination and state filter | `Promise<SandboxListResponse>` | List Sandboxes for the account. |
| `create({ ...body }?)` | optional `type`, `ttlSeconds`, `env`, `environment`, `noEnv`, `setupScript`, `from`, `org` | `Promise<CreateSandboxResponse>` | Create a sandbox. Use `ttlSeconds: null` to disable auto-stop. Set `noEnv: true` to withhold all account secrets (for sandboxes you give to your users). `from` starts the sandbox from a named snapshot; `org` bills it to an organization wallet. |
| `get({ sandboxId })` | Sandbox id | `Promise<SandboxInfoResponse>` | Fetch the latest sandbox state and connection fields. |
| `usage({ sandboxId, since, until })` | Sandbox id, optional window as ISO 8601 or Unix seconds | `Promise<SandboxUsageResponse>` | Billable machine time one sandbox consumed, and its cost at list price, for per-sandbox billing of your own users. Omit the window for the sandbox's whole life. See [Per-sandbox usage](/billing#per-sandbox-usage). |
| `update({ sandboxId, ...body })` | Sandbox id plus `name`, `ttlSeconds`, and/or `subdomain` | `Promise<SandboxInfoResponse>` | Rename a sandbox, change its auto-stop TTL, or rename its subdomain (re-points every live URL with no downtime). |
| `stop({ sandboxId, ...body }?)` | Sandbox id, optional `force` | `Promise<SandboxActionResponse>` | Stop/archive a sandbox. A stop snapshots the disk first; if that is failing the stop is refused and the sandbox keeps running (you are not billed for that time). Pass `force: true` to stop anyway and permanently lose everything written since the last successful snapshot. |
| `resume({ sandboxId, ...body })` | Sandbox id, optional `type`, `env`, `environment`, `ttlSeconds`, `noEnv` | `Promise<SandboxActionResponse>` | Resume an archived sandbox. Set `noEnv: true` to convert it to no-env while scrubbing inherited owner secrets, or `type` to resume it onto a different machine size. `ttlSeconds` is omitted to keep the sandbox's current auto-stop. Poll `get()` until it is ready. |
| `fork({ sandboxId, ...body })` | Sandbox id, optional `env`, `environment`, `type`, `ttlSeconds`, `noEnv` | `Promise<SandboxActionResponse>` | Create a new Sandbox from the source sandbox snapshot. Set `noEnv: true` to create a no-env fork, or `type` to fork onto a different machine size. A fork does not inherit the source's auto-stop: omit `ttlSeconds` and it gets the 1 hour default. The source sandbox is never modified. |
| `deleteSandbox({ sandboxId })` | Sandbox id | `Promise<SandboxActionResponse>` | **Permanently delete a sandbox and its snapshots.** Force-stops it, then deletes every snapshot chain only this sandbox uses. It cannot be resumed or forked afterwards and there is no undo, so use `stop()` if you want the data back later. Snapshot data a fork, a resume or a named snapshot still reads is kept. See [Snapshots](/snapshots#deleting-a-sandboxs-snapshots). |
| `prompt({ sandboxId, ...body })` | Sandbox id plus `provider`, `prompt`, optional `model`, optional `reasoningEffort`, optional `fast`, optional `new`, optional `conversationId` | `Promise<PromptResponse>` | Queue work inside a sandbox. Returns `promptId`, `promptRun.status`, and the `conversationId` it ran in. Set `new: true` for a new [conversation](/integrated-agents) or `conversationId` to continue one. Set `fast: true` to run in fast mode. |
| `promptRunStatus({ sandboxId, promptId })` | Sandbox id and prompt id | `Promise<PromptRunResponse>` | Read first-class prompt run status, including its `conversationId`. |
| `events({ sandboxId, limit, cursor, sort, type, conversation })` | Sandbox id plus optional pagination/filtering | `Promise<EventsResponse>` | Read typed event history for a sandbox. Streams all [conversations](/integrated-agents) by default; pass `conversation` to filter. Each event carries `conversationId`. |
| `readFile({ sandboxId, path, encoding })` | Sandbox id and relative path | `Promise<FileReadResponse>` | Deterministically read a text/base64 file from the sandbox work directory. |
| `writeFile({ sandboxId, ...body })` | Sandbox id plus relative path/content | `Promise<FileWriteResponse>` | Deterministically write a text/base64 file. |
| `command({ sandboxId, ...body })` | Sandbox id plus command/cwd/timeout | `Promise<CommandResponse>` | Execute a bounded command in the sandbox work directory. |
| `artifact({ sandboxId, path })` | Sandbox id and relative path | `Promise<Blob>` | Download an artifact as bytes. |
| `interrupt({ sandboxId })` | Sandbox id | `Promise<SandboxActionResponse>` | Interrupt current work in a running sandbox. |
| `desktop({ sandboxId, vnc, theme, requestBody })` | Sandbox id plus optional desktop parameters. For VNC, send `requestBody: { publicAccess: true }` to return a URL without `_token`. | `Promise<DesktopResponse>` | Create or fetch a desktop streaming URL. Treat returned URLs as secrets. If `provisioning` is true, poll again. |
| `sshKey({ sandboxId, ...body })` | Sandbox id plus public SSH key | `Promise<SshKeyResponse>` | Add a public SSH key for sandbox SSH access. |
| `listSnapshots({ limit, cursor, sort }?)` | optional pagination | `Promise<SnapshotListResponse>` | List completed snapshots across all sandboxes; each item carries its `sandboxId`. |
| `listSandboxSnapshots({ sandboxId, limit, cursor, sort })` | Sandbox id plus optional pagination | `Promise<SnapshotListResponse>` | List completed snapshots for one sandbox. |
| `getLatestSandboxSnapshot({ sandboxId })` | Sandbox id | `Promise<SnapshotLatestResponse>` | Most recent completed snapshot for a sandbox, or `null`. |
| `getSnapshotTree({ snapshotId })` | Snapshot id | `Promise<SnapshotTreeResponse>` | Flat file/folder listing with sizes for a snapshot. Works with the sandbox stopped or archived. |
| `getSnapshotFile({ snapshotId, path })` | Snapshot id plus a path from the tree (empty for the whole snapshot) | `Promise<Blob>` | Download one file's bytes, or a folder as a `.tar` archive, straight from the snapshot. Works with the sandbox stopped or archived. |
| `getSnapshotDownload({ snapshotId })` | Snapshot id | `Promise<SnapshotDownloadResponse>` | Signed chunk URLs to rebuild the snapshot's full filesystem client-side. |

### Browse a stopped sandbox's filesystem

Snapshot reads never touch the machine, so they work while the sandbox is archived:

```ts theme={null}
const latest = await sandbox.getLatestSandboxSnapshot({ sandboxId });
const tree = await sandbox.getSnapshotTree({ snapshotId: latest.snapshot.id });
const blob = await sandbox.getSnapshotFile({ snapshotId: latest.snapshot.id, path: "projects/app/.env" });
```

## Waiters and helpers

The package exports first-class waiters and deterministic file/command helper functions:

```ts theme={null}
import { waitUntilReady, waitUntilIdle, waitForDesktop, waitForPrompt, waitForPromptDone, streamEvents, streamPrompt, stopAndRemove, readText, writeText, execCommand } from "@boatdev/sdk";

await waitUntilReady(sandbox, sandboxId);
const queued = await sandbox.prompt({ sandboxId, provider: "codex", prompt: "Run tests" });
// fast mode instead: { sandboxId, provider: "codex", model: "gpt-6.1-sol", fast: true, prompt: "Run tests" }
await waitForPrompt(sandbox, sandboxId, queued.promptId);
const publicVnc = await waitForDesktop(sandbox, sandboxId, { publicAccess: true });
await writeText(sandbox, sandboxId, "notes/result.txt", "done\n");
const result = await execCommand(sandbox, sandboxId, "cat notes/result.txt");
await stopAndRemove(sandbox, sandboxId);                      // stop, keep the snapshots
await stopAndRemove(sandbox, sandboxId, { delete: true });    // delete the sandbox and its snapshots
```

Use `waitForPrompt`/`waitForPromptDone` instead of inferring completion from `sandbox.state` plus event polling. Use `streamPrompt` or `streamEvents` when you need incremental response/tool-call events as work runs.

## Streaming responses and tool calls

The SDK now exports `streamEvents` and `streamPrompt` for response streaming. They use the sandbox v1 events cursor API under the hood, so no separate SSE or WebSocket endpoint is required. `response` events carry text in `event.data.content`; streaming partials set `event.data.isStreaming`; tool-call events are `response` events with `event.data.tools`.

```ts theme={null}
import { BoatApi, Configuration, streamPrompt } from "@boatdev/sdk";

const sandbox = new BoatApi(new Configuration({
  basePath: "https://boat.dev/api/v1",
  accessToken: process.env.BOAT_API_KEY!,
}));

const stream = streamPrompt(sandbox, sandboxId, {
  provider: "codex",
  prompt: "Run pwd and ls, then summarize the result.",
});

for await (const event of stream) {
  if (event.type !== "response") continue;
  const data = event.data;
  if (data.tools?.length) console.log("tools", data.tools);
  if (data.content) process.stdout.write(data.content);
  if (data.isStreaming) process.stdout.write("\n[partial]\n");
}
```

For a dashboard-style feed not tied to one prompt, use `streamEvents(sandbox, sandboxId, { type: "prompt,response" })` and stop it with an `AbortController`.

## Operation request types

These exported interfaces wrap method parameters for `BoatApi` methods.

| Type | Fields | Used by |
| - | - | - |
| `ArtifactRequest` | `sandboxId`, `path` | `artifact()` |
| `SandboxesRequest` | `limit`, `cursor`, `sort`, `state` | `sandboxes()` |
| `CommandOperationRequest` | `sandboxId`, `commandRequest` | `command()` |
| `CreateRequest` | `createSandboxRequest` | `create()` |
| `DesktopRequest` | `sandboxId`, `vnc`, `theme`, `requestBody` | `desktop()`; set `requestBody.publicAccess` for an ungated VNC URL. |
| `EventsRequest` | `sandboxId`, `limit`, `cursor`, `sort`, `type`, `conversation` | `events()`; `conversation` filters to one [conversation](/integrated-agents). |
| `ForkRequest` | `env`, `environment`, `type`, `ttlSeconds`, `noEnv` | `fork()` |
| `GetRequest` | `sandboxId` | `get()` |
| `UsageRequest` | `sandboxId`, `since`, `until` | `usage()` |
| `InterruptRequest` | `sandboxId`, `conversation` | `interrupt()`; omit `conversation` to stop the whole sandbox, or pass one to scope it. |
| `PromptOperationRequest` | `sandboxId`, `promptRequest` | `prompt()` |
| `PromptRunStatusRequest` | `sandboxId`, `promptId` | `promptRunStatus()` |
| `ReadFileRequest` | `sandboxId`, `path`, `encoding` | `readFile()` |
| `RemoveRequest` | `sandboxId` | `remove()` |
| `ReposRequest` | `sync`, `limit`, `cursor`, `sort`, `q`, `selected` | `repos()` |
| `ResumeRequest` | `type`, `env`, `environment`, `ttlSeconds`, `noEnv` | `resume()` |
| `SelectRepoRequest` | `repoSelectionRequest` | `selectRepo()` |
| `SshKeyOperationRequest` | `sandboxId`, `sshKeyRequest` | `sshKey()` |
| `StopRequest` | `sandboxId` | `stop()` |
| `UpdateRequest` | `sandboxId`, `updateSandboxRequest` | `update()` |
| `UpdateSecretsRequest` | `secretsUpdateRequest` | `updateSecrets()` |
| `WriteFileRequest` | `sandboxId`, `fileWriteRequest` | `writeFile()` |
| `SandboxesSortEnum` | `"asc"`, `"desc"` | `sandboxes({ sort })` |
| `DesktopVncEnum` | `1` | `desktop({ vnc })` |
| `DesktopThemeEnum` | `"light"`, `"dark"` | `desktop({ theme })` |
| `EventsSortEnum` | `"asc"`, `"desc"` | `events({ sort })` |
| `ReadFileEncodingEnum` | `"utf8"`, `"base64"` | `readFile({ encoding })` |
| `ReposSortEnum` | `"asc"`, `"desc"` | `repos({ sort })` |

## Model types

TypeScript models use camelCase fields.

| Type | Fields | Notes |
| - | - | - |
| `ApiKey` | `id`, `name`, `keyPrefix`, `keyLastFour`, `createdAt`, `lastUsedAt`, `usage`, `resources` | Metadata only; not the raw secret. Includes 30-day request total and live resource counts. |
| `ApiKeysResponse` | `ok`, `type`, `apiKeys` | API key metadata response. Raw secrets are not returned. |
| `Sandbox` | `id`, `name`, `state`, `type`, `vcpu`, `memoryGB`, `billingMultiplier`, `url`, `ip`, `createdAt`, `updatedAt`, `archiveAfter`, `desktopAvailable`, `desktopUrl`, `snapshotAvailable`, `snapshotCompletedAt` | `desktopUrl` can contain a token; redact it. |
| `SandboxActionResponse` | `ok`, `type`, `id`, `status`, `sandbox` | Returned by lifecycle actions such as stop, resume, fork, and interrupt. |
| `SandboxInfoResponse` | `ok`, `type`, `sandbox` | Returned by `get()` and `update()`. |
| `SandboxUsageResponse` | `ok`, `type`, `sandboxId`, `sandboxType`, `billingMultiplier`, `since`, `until`, `seconds`, `dollars`, `secondsPerDollar`, `running` | Returned by `usage()`. `seconds` has the type multiplier applied; `running` means it is still growing. |
| `SandboxEvent` | `id`, `type`, `timestamp`, `taskId`, `conversationId`, `data`, plus additional fields | Extensible event object returned inside `EventsResponse.events`. `conversationId` tells you which [conversation](/integrated-agents) the event belongs to. Branch on each event `type`. |
| `SandboxListResponse` | `ok`, `type`, `sandboxes`, `pageInfo` | Returned by `sandboxes()`. |
| `CommandRequest` | `command`, `cwd`, `timeoutSeconds` | Bounded command execution request. |
| `CommandResponse` | `ok`, `type`, `success`, `exitCode`, `signal`, `stdout`, `stderr`, `stdoutTruncated`, `stderrTruncated`, `timedOut`, `cwd`, `startedAt`, `finishedAt` | Returned by `command()` and `execCommand()`. |
| `CompletionEvent` | `id`, `type`, `timestamp`, `taskId`, `data` | Event subtype for `task_notification` and `compaction_complete`. |
| `CreateSandboxRequest` | `type`, `ttlSeconds`, `env`, `environment`, `noEnv`, `setupScript`, `from`, `org` | `type` is `small`, `default` or `large` (see Machine size). `ttlSeconds` is the delay before auto-stop; `null` disables it. `from` names a snapshot to start from; `org` bills the sandbox to an organization wallet. |
| `CreateSandboxResponse` | `ok`, `type`, `status`, `ttlSeconds`, `sandbox` | Returned immediately after creation starts. |
| `DesktopResponse` | `ok`, `type`, `success`, `desktopUrl`, `ip`, `mode`, `provisioning`, `message` | If `provisioning` is true, poll `desktop()` again. |
| `ErrorEnvelope` | `ok`, `type`, `status`, `code`, `message`, `requestId`, `error` | Non-2xx response body. Include `requestId` in support logs. |
| `ErrorEnvelopeError` | `code`, `message`, `status`, `details` | Structured error details. |
| `ErrorEvent` | `id`, `type`, `timestamp`, `taskId`, `data` | Event subtype for `usage_limit` and `shield`. |
| `EventsResponse` | `ok`, `type`, `id`, `events`, `pageInfo` | `events` contains sandbox event objects. |
| `FileReadResponse` | `ok`, `type`, `success`, `path`, `encoding`, `size`, `content` | Returned by `readFile()` and `readText()`. |
| `FileWriteRequest` | `path`, `content`, `encoding` | Write a UTF-8 string or base64 payload. |
| `FileWriteResponse` | `ok`, `type`, `success`, `path`, `encoding`, `size` | Returned by `writeFile()` and `writeText()`. |
| `LimitsFields` | `accessTier`, `blockedReason`, `currentLimits`, `standardLimits`, `trialLimits`, `upgradeEffects`, `canStart`, `checkoutRequired`, `startBlockedReason`, `contactMessage`, `activeSandboxes`, `activeStates`, `maxActiveSandboxes`, `maxCreationRequestsPerMinute`, `maxCreationRequestsPerDay`, `startLimits`, `starts`, `accountPlan`, `plan`, `planName`, `serviceAccount`, `unlimited`, `hasPaymentHistory`, `_package`, `subscriptionQuotaSeconds`, `subscriptionRemainingSeconds`, `packBalanceSeconds`, `packBalanceHours`, `packBalanceDollars`, `creditPurchasedSeconds`, `creditUsedSeconds`, `liveUsageSeconds`, `creditSecondsPerDollar`, `billingStatus`, `subscriptionStatus`, `subscriptionCancelAtPeriodEnd`, `hasSubscription`, `subscriptionTrialEndsAt`, `subscriptionCurrentPeriodEnd`, `creditBalanceSeconds`, `creditBalanceHours` | Shared limit and billing-access fields. Use `canStart` and `startBlockedReason` before creating sandboxes. `starts.*.remaining` is remaining machine starts in each rolling window. `serviceAccount`/`unlimited` identify admin-created automation accounts. |
| `LimitsFieldsCurrentLimits` | `activeSandboxes`, `creationRatePerMinute`, `creationRequestsPerDay` | Numeric quota limits. |
| `LimitsResponse` | `ok`, `type`, plus all `LimitsFields` fields | Returned by `limits()`. |
| `MeResponse` | `ok`, `type`, `user` | Authenticated account response. |
| `MeResponseAllOfUser` | `login`, `email` | User identity fields. |
| `PageInfo` | `nextCursor`, `hasMore`, `limit` | Optional pagination metadata on list responses. |
| `PromptEvent` | `id`, `type`, `timestamp`, `taskId`, `conversationId`, `data` | Event subtype for `prompt`. |
| `PromptEventData` | `prompt`, `status`, `isReverted` | Prompt event payload. |
| `PromptRequest` | `provider`, `model`, `reasoningEffort`, `fast`, `new`, `conversationId`, `prompt` | `provider` is `codex`, `claude-code` (alias `claude`), `pi`, `opencode`, `prime-agent` (alias `prime`), `kimi`, or `mistral`; omit it for the dashboard default. Omit `model`/`reasoningEffort`/`fast` to use saved defaults (live catalog: `GET /provider-models`). `fast: true` runs in fast mode at the provider's higher fast rate. Only models with `fastMode: true` accept it; others return `fast_mode_not_supported`. Set `new: true` or `conversationId` to control the [conversation](/integrated-agents). |
| `PromptResponse` | `ok`, `type`, `id`, `promptId`, `conversationId`, `promptRun`, `status`, `provider`, `model`, `reasoningEffort`, `fast` | Returned after work is queued. `conversationId` is the conversation the prompt runs in. |
| `PromptRun` | `id`, `promptId`, `sandboxId`, `status`, `done`, `createdAt`, `model`, `reasoningEffort`, `fast`, `conversationId` | First-class prompt run state. |
| `PromptRunResponse` | `ok`, `type`, `id`, `promptRun` | Returned by `promptRunStatus()`. |
| `ResponseEvent` | `id`, `type`, `timestamp`, `taskId`, `conversationId`, `data` | Event subtype for `response`. |
| `ResponseEventData` | `content`, `model`, `tools`, `isStreaming` | Response event payload. |
| `RepoSelectionRequest` | `repositoryId`, `baseBranch` | `repositoryId` is a `databaseId` from `repos()`. |
| `RepoSelectionResponse` | `ok`, `type`, `success`, `environmentId`, `selectedRepositories` | Returned by `selectRepo()`. |
| `ReposResponse` | `ok`, `type`, `installations`, `environmentId`, `selectedRepositories`, `pageInfo` | Repository inventory and current selections. |
| `Repository` | `id`, `databaseId`, `name`, `fullName`, `_private`, `permissions`, `pushedAt` | Use `databaseId` when selecting a repository. |
| `RepositoryInstallation` | `type`, `accountLogin`, `accountAvatarUrl`, `repositories` | Group of repositories available through one installation/account. |
| `SecretFile` | `path`, `contents` | Treat `contents` as sensitive. |
| `SecretsResponse` | `ok`, `type`, `success`, `environmentId`, `envContents`, `secretFiles`, `pushed` | Current secret setup. Treat `envContents` and `secretFiles` as sensitive. |
| `SecretsUpdateRequest` | `envContents`, `secretFiles` | Full replacement request for secrets. |
| `SelectedRepository` | `id`, `databaseId`, `name`, `fullName`, `_private`, `permissions`, `pushedAt`, `baseBranch`, `setupRoutineId`, `setupScript`, `setupBlocking` | Repository selected for future sandboxes. |
| `SshKeyRequest` | `key` | Public SSH key in OpenSSH format. |
| `SshKeyResponse` | `ok`, `type`, `success`, `machineIp`, `sshUser` | Returned after adding an SSH key. |
| `SuccessBase` | `ok`, `type` | Base success-envelope fields. |
| `UnknownEvent` | `type`, plus additional properties | Forward-compatible fallback for event types the SDK does not model yet. |
| `UpdateSandboxRequest` | `name`, `ttlSeconds` | Send only fields you want to change. `ttlSeconds: null` disables auto-stop. |

## Errors

Non-2xx responses reject with a `ResponseError`. Read the status and parse the JSON body for the structured Boat error envelope. Redact API keys, Boat secrets, SSH keys, and desktop URLs.

```ts theme={null}
import { ResponseError } from "@boatdev/sdk";

try {
  await sandbox.get({ sandboxId: "bx_missing" });
} catch (error) {
  if (error instanceof ResponseError) {
    console.error(error.response.status);
    console.error(await error.response.json());
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.