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

# TypeScript SDK

> @usenaive-sdk/vetta — the published typed client for the Vetta API, documented method by method from the source.

<Note>**This page is the map; the per-namespace pages are the territory.** The [method index](#method-index) below is generated from the client source and checked against the constructed client, so it cannot name a method the package does not export — and every namespace links to a page documenting each method's signature, route, and semantics. TypeScript only; there is no Python package.</Note>

```bash theme={"system"}
npm i @usenaive-sdk/vetta
```

The build bundles the private `@vetta/core` into `dist/`, so the installed package resolves against
nothing but `zod`. Inside this repository it resolves as a workspace dependency, which is how
`apps/cli` and the dashboard consume it. Everything documented below is the real, current surface
of `packages/sdk`.

`@usenaive-sdk/vetta` is the one place that knows how to talk to the control plane over HTTP. `apps/cli` and the dashboard both go through it, which is the whole reason it exists: the bearer key, the `Vetta-Version` pin, the `Idempotency-Key` on every mutating verb, and the error envelope are decided **once**, in `src/http.ts`, instead of twice and slightly differently.

## What it is not

It is deliberately thinner than a product SDK:

* **No retry policy.** A caller that wants retries owns that decision, because the CLI and the dashboard want different ones.
* **No pagination magic.** `list` returns one page and the cursor. No auto-paging iterator.
* **No client-side taxonomy.** `ApiError.type` and `ApiError.status` are read off the response. The server owns the code → (type, status) table; a second copy here would be a second taxonomy that could drift.
* **No wire shapes of its own.** Responses parse with the zod schemas from `@vetta/core`. Where a body is not yet modelled there — shell exec, billing, the per-op `fs` replies — the client says so explicitly with a local schema or `RawSchema`, rather than inventing a type.

## Constructing a client

Everything the client cannot decide for itself is injected. That is not ceremony: it is what lets the test suite assert exact traffic against a recording `fetch`, and what lets the CLI own the real one.

```ts theme={"system"}
import { randomUUID } from "node:crypto";
import { createClient } from "@usenaive-sdk/vetta";

const client = createClient({
  baseUrl: "https://api.vetta.sh",
  apiKey: process.env.VETTA_API_KEY!,
  fetch: globalThis.fetch,
  idempotencyKey: () => randomUUID(),
});
```

<ResponseField name="baseUrl" type="string" required>Control-plane origin. Trailing slashes are trimmed.</ResponseField>
<ResponseField name="apiKey" type="string" required>Sent as `Authorization: Bearer …`. One client per credential — `vetta login` has none until the sign-in reply comes back.</ResponseField>
<ResponseField name="fetch" type="typeof fetch" required>Injected so tests can record and the CLI can wrap it (it names the host in connection errors).</ResponseField>
<ResponseField name="idempotencyKey" type="() => string" required>Called once per mutating verb. Injected so a test gets a deterministic key.</ResponseField>

## Coverage

The method table is the route table. The API serves **132 routes across 95 paths**; the client reaches **89 of those 95 paths** from exactly one method each, across twenty namespaces:

| Namespace                                                                                                            | Covers                                                                      |
| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| [`agents`](/docs/sdk/agents) [`sessions`](/docs/sdk/sessions) [`models`](/docs/sdk/models)                                          | The control plane — agents, versions, personas, runs, budgets, cancellation |
| [`computers`](/docs/sdk/computers) [`skills`](/docs/sdk/skills) [`files`](/docs/sdk/files)                                          | The three resources a session works with                                    |
| [`identities`](/docs/sdk/identities) [`connections`](/docs/sdk/connections) [`vaults`](/docs/sdk/vaults)                            | Personas, external tool auth, credentials                                   |
| [`domains`](/docs/sdk/domains) [`emails`](/docs/sdk/emails) [`phones`](/docs/sdk/phones)                                            | The identity's reachable surface                                            |
| [`deployments`](/docs/sdk/deployments) [`webhooks`](/docs/sdk/webhooks)                                                        | Schedules and delivery                                                      |
| [`auth`](/docs/sdk/auth) [`orgs`](/docs/sdk/orgs) [`keys`](/docs/sdk/keys) [`credits`](/docs/sdk/credits) [`auditLogs`](/docs/sdk/audit-logs) | Account, members, scoped keys, prepaid balance, audit trail                 |
| [`stream`](/docs/sdk/streaming)                                                                                           | The resumable SSE consumer                                                  |

Cross-cutting behavior has its own pages too: [Errors](/docs/sdk/errors), [Pagination](/docs/sdk/pagination), and [Streaming](/docs/sdk/streaming).

Two methods are parameterized over a family rather than split per route, because splitting them would produce five near-identical methods with no added type safety:

* `computers.fs(id, op, body)` reaches all five `/v1/computers/{id}/fs/*` routes. The reply differs per op (`{content}`, `{entries}`, `{created}`…), so it comes back as `RawSchema`.
* `stream(sessionId, options)` is the one consumer of `GET /v1/sessions/{id}/stream`.

**Six routes are deliberately absent**, and they are the whole difference between 95 paths and 89:

| Absent route                 | Why no method                                                                                                                                                   |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/v1/webhooks/stripe`        | Inbound billing callback. The provider calls it and authenticates with a signature, not a key.                                                                  |
| `/v1/webhooks/inbound/email` | Inbound mail receiver. Same: called by the provider, never by you.                                                                                              |
| `/v1/webhooks/inbound/sms`   | Inbound SMS receiver. Same.                                                                                                                                     |
| `/v1/openapi.json`           | The machine-readable description of this same surface. Fetch it with `fetch`; a typed method for it would describe itself.                                      |
| `/v1/auth/confirmed_users`   | Operator-only, gated by the deployment's bootstrap token rather than an API key. No customer credential can call it, so a typed method would only invite a 401. |
| `/v1/mcp`                    | JSON-RPC, not REST: the [MCP tool catalog](/docs/api/mcp) an agent's runtime speaks. Every operation behind it already has a typed method here.                      |

That accounting is generated, not asserted by hand — `scripts/interface-parity` rebuilds it from the route table, the client source and this page.

<Note>**Do not write those five paths on this page with an HTTP verb in front of them.** `apps/api/test/drift.e2e.ts` scans every published `docs/**.mdx` for `METHOD /v1/…` to learn what the docs promise a customer. Pairing a verb with one of these paths would register a deliberately-unpublished route as documented and quietly retire the allowance that keeps it honest.</Note>

## Invariants worth knowing before your first call

### Money is integer micro-USD, always

Every monetary field on every signature is `z.number().int()`. The client never exposes a float and never converts to dollars — formatting is a presentation decision, and doing it here once cost a 10⁶ error in an earlier audit. `credits.topup` takes `amountMicroUsd`; `sessions.setBudget` takes `capMicroUsd`.

### The vault has no read method, by contract

`vaults` exposes `create`, `list`, `get`, `delete` and `credentials.{create,list,delete}` — and no reveal. The control plane serves no reveal route and `VaultCredentialSchema` has no `value` field, so `list` could not return one even if a handler tried. **Do not add one.** Rotation is create-new + delete-old rather than an `update`, so `last_injected_at` stays attributable to exactly one secret.

### The two skill pushes are not interchangeable

`skills.push({ slug, content })` hits `POST /v1/skills` and is create-or-version *by slug*: unknown slug creates the skill. `skills.pushVersion(ref, { content })` hits `POST /v1/skills/{id}/versions` and requires the skill to exist — an unknown ref is a 404, not a create. A release pipeline pinned to a skill id wants the second one, so a rename cannot silently mint a second skill.

Both accept an optional `sha256`. It is an *integrity claim the server checks against its own digest*, never the digest of record. A mismatch is rejected.

## Worked examples

Every block below was run against staging on 2026-08-22. Replies are shown as returned, except the
two marked as abridged.

### Reading the balance

```ts theme={"system"}
const balance = await client.credits.show();
```

```json theme={"system"}
{ "object": "credit_balance", "balance_micro_usd": 79416537, "mode": "test" }
```

`79416537` micro-USD is \$79.416537. The client hands you the integer; you format it.

### Pushing a skill, then a second version of it

```ts theme={"system"}
const v1 = await client.skills.push({
  slug: "parity-demo-5e66aacb",
  content: "# Demo\nfirst.\n",
  description: "parity demo",
});
const v2 = await client.skills.pushVersion(v1.id, { content: "# Demo\nsecond.\n" });
```

```json theme={"system"}
{"version":1,"sha256":"5f22eb6cabbfe6b898548754a4da28d7e6d4e54d53a80780088d28662fe4869f","size_bytes":14,"created_at":"2026-08-23T00:44:28.415Z","id":"skl_e4dpzg0b1yxzhngqfzdanqxqa1","slug":"parity-demo-5e66aacb"}
{"version":2,"sha256":"84876f29ae4f70fe355c10186c5986e0db2d6c4b5fcd60a47b5bfe023b04b03e","size_bytes":15,"created_at":"2026-08-23T00:44:30.056Z","id":"skl_e4dpzg0b1yxzhngqfzdanqxqa1","slug":"parity-demo-5e66aacb"}
```

Note `id` and `slug` on the reply. They are what makes the chain above work, and they are the reason pushes parse with `SkillPushSchema` (`core`'s `SkillVersionSchema` extended) rather than the bare version schema, which would strip them.

### Why `pushVersion` is not just `push`

```ts theme={"system"}
await client.skills.pushVersion("skl_does_not_exist", { content: "x" });
```

```
ApiError status=404 code=not_found type=not_found message=no such skill: skl_does_not_exist
```

`push` with an unknown slug would have created a skill. That is the entire difference.

### The integrity claim is checked, not trusted

```ts theme={"system"}
await client.skills.pushVersion(slug, { content: "# Demo\nthird.\n", sha256: "0".repeat(64) });
```

```
ApiError status=400 code=validation_failed param=sha256 message=sha256 does not match the content
```

`ApiError.param` names the offending field, which is what the CLI prints.

### Listing versions

```ts theme={"system"}
const versions = await client.skills.listVersions(slug);
```

```json theme={"system"}
{ "data": [{ "version": 2, "sha256": "84876f29ae4f…" }, { "version": 1, "sha256": "5f22eb6cabbf…" }], "has_more": false, "next_cursor": null }
```

Abridged: the digests are full 64-character hexes. Newest first. The cursor is the version number, not an id — versions have none of their own.

### The page envelope

```ts theme={"system"}
const agents = await client.agents.list({ limit: 2 });
```

```json theme={"system"}
{ "data": [ { "id": "agt_…", "name": "e2e-toolfail-1787443045296" }, { "id": "agt_…" } ], "has_more": true, "next_cursor": "agt_…" }
```

Abridged: the two agent objects are full agents. `{ data, has_more, next_cursor }` on every list. There is no auto-paging helper; pass `after: next_cursor`.

### Deleting

```ts theme={"system"}
await client.skills.delete(slug);
```

```json theme={"system"}
{ "id": "skl_e4dpzg0b1yxzhngqfzdanqxqa1", "object": "skill", "deleted": true }
```

Every delete answers the same `{ id, object, deleted }` acknowledgement.

## Handling errors

Every non-2xx throws `ApiError`. There is one shape:

```ts theme={"system"}
import { ApiError } from "@usenaive-sdk/vetta";

try {
  await client.skills.get("skl_nope");
} catch (error) {
  if (error instanceof ApiError) {
    // error.status  404
    // error.type    "not_found"
    // error.code    "not_found"
    // error.param   the offending field, when the server names one
    // error.requestId  quote this in a bug report
  }
}
```

`requestId` is the single most useful field in a report — it is the server's own correlation id for that call.

## Streaming

`stream` is a resumable async generator over session events. `afterSeq` is **exclusive**, so resuming from the last seq you saw does not replay it:

```ts theme={"system"}
let last = 0;
for await (const event of client.stream(sessionId, { afterSeq: last })) {
  last = event.seq;
}
```

The dashboard does not call this directly. It re-serves the SSE body same-origin using the `send` escape hatch, so the control-plane key never reaches a browser.

## The same operation in the other two interfaces

Every method below has a counterpart in the [CLI](/docs/cli/overview) and a page in the [API reference](/docs/api/overview), named the same way. The three surfaces are generated against one route table, so a gap in any of them is a build failure rather than a discovery.

| SDK                                                                           | CLI                                                                                                                 | API                                                                                           |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `client.agents.create`                                                        | [`vetta agent create`](/docs/cli/agents)                                                                                 | [Agents](/docs/api/agents)                                                                         |
| `client.sessions.create` · `client.stream`                                    | [`vetta session create`](/docs/cli/sessions) · [`vetta run`](/docs/cli/sessions)                                              | [Sessions](/docs/api/sessions) · [Events](/docs/api/events)                                             |
| `client.computers.*`                                                          | [`vetta computer`](/docs/cli/computer)                                                                                   | [Computers](/docs/api/computers)                                                                   |
| `client.skills.push` · `client.skills.pushVersion`                            | [`vetta skill push`](/docs/cli/skills) · [`vetta skill push-version`](/docs/cli/skills)                                       | [Skills](/docs/api/skills)                                                                         |
| `client.files.*`                                                              | [`vetta file`](/docs/cli/files)                                                                                          | [Files](/docs/api/files)                                                                           |
| `client.deployments.*` · `client.webhooks.*`                                  | [`vetta deploy`](/docs/cli/deployments) · [`vetta webhook`](/docs/cli/webhook)                                                | [Deployments](/docs/api/deployments) · [Webhooks](/docs/api/webhooks)                                   |
| `client.orgs.*` · `client.keys.*` · `client.credits.*` · `client.auditLogs.*` | [`vetta org`](/docs/cli/org) · [`vetta keys`](/docs/cli/keys) · [`vetta credits`](/docs/cli/billing) · [`vetta audit`](/docs/cli/audit) | [Organizations](/docs/api/organizations) · [Credits](/docs/api/credits) · [Audit logs](/docs/api/audit-logs) |
| `client.auth.*`                                                               | [`vetta auth`](/docs/cli/auth)                                                                                           | [Authentication](/docs/api/authentication)                                                         |
| `client.identities.*` · `client.connections.*` · `client.vaults.*`            | [`vetta identity`](/docs/cli/identity) · [`vetta vault`](/docs/cli/vault)                                                     | [Identities](/docs/api/identities) · [Connections](/docs/api/connections) · [Vaults](/docs/api/vaults)       |
| `client.domains.*` · `client.emails.*` · `client.phones.*`                    | [`vetta identity domain`](/docs/cli/comms) · [`vetta identity email`](/docs/cli/comms) · [`vetta identity phone`](/docs/cli/phone) | [Domains](/docs/api/domains) · [Messaging](/docs/api/messaging)                                         |

## Method index

Every method on the client, and the route it calls — 179 methods across 26 namespaces. Generated from the client source by `scripts/sdk-index.mjs`; the drift gate fails if it falls behind.

### `agents`

| Method                | Route                               |
| --------------------- | ----------------------------------- |
| `agents.create`       | `POST /v1/agents`                   |
| `agents.delete`       | `DELETE /v1/agents/{id}`            |
| `agents.get`          | `GET /v1/agents/{id}`               |
| `agents.getVersion`   | `GET /v1/agents/{id}/versions/{id}` |
| `agents.list`         | `GET /v1/agents`                    |
| `agents.listVersions` | `GET /v1/agents/{id}/versions`      |
| `agents.rollback`     | `POST /v1/agents/{id}/rollback`     |
| `agents.spend`        | `GET /v1/agents/{id}/spend`         |
| `agents.update`       | `PATCH /v1/agents/{id}`             |

### `apps`

| Method                  | Route                               |
| ----------------------- | ----------------------------------- |
| `apps.artifacts.list`   | `GET /v1/blueprints/artifacts`      |
| `apps.connectDomain`    | `POST /v1/apps/{id}/domains`        |
| `apps.create`           | `POST /v1/apps`                     |
| `apps.delete`           | `DELETE /v1/apps/{id}`              |
| `apps.deleteSecret`     | `DELETE /v1/apps/{id}/secrets/{id}` |
| `apps.deploy`           | `POST /v1/apps/{id}/deployments`    |
| `apps.deployments`      | `GET /v1/apps/{id}/deployments`     |
| `apps.disconnectDomain` | `DELETE /v1/apps/{id}/domains/{id}` |
| `apps.domains`          | `GET /v1/apps/{id}/domains`         |
| `apps.entry`            | `POST /v1/apps/{id}/entry`          |
| `apps.get`              | `GET /v1/apps/{id}`                 |
| `apps.installs.apply`   | `POST /v1/blueprints/installs`      |
| `apps.installs.list`    | `GET /v1/blueprints/installs`       |
| `apps.list`             | `GET /v1/apps`                      |
| `apps.query`            | `POST /v1/apps/{id}/db/query`       |
| `apps.secrets`          | `GET /v1/apps/{id}/secrets`         |
| `apps.setSecret`        | `POST /v1/apps/{id}/secrets`        |
| `apps.update`           | `PATCH /v1/apps/{id}`               |

### `auditLogs`

| Method           | Route                |
| ---------------- | -------------------- |
| `auditLogs.list` | `GET /v1/audit_logs` |

### `auth`

| Method                    | Route                         |
| ------------------------- | ----------------------------- |
| `auth.me`                 | `GET /v1/me`                  |
| `auth.recover`            | `POST /v1/auth/recover`       |
| `auth.register`           | `POST /v1/auth/users`         |
| `auth.resendConfirmation` | `POST /v1/auth/confirmations` |
| `auth.resetPassword`      | `POST /v1/auth/password`      |
| `auth.session`            | `POST /v1/auth/session`       |

### `board`

| Method                 | Route                                      |
| ---------------------- | ------------------------------------------ |
| `board.cards.comment`  | `POST /v1/boards/{id}/cards/{id}/comments` |
| `board.cards.comments` | `GET /v1/boards/{id}/cards/{id}/comments`  |
| `board.cards.create`   | `POST /v1/boards/{id}/cards`               |
| `board.cards.get`      | `GET /v1/boards/{id}/cards/{id}`           |
| `board.cards.list`     | `GET /v1/boards/{id}/cards`                |
| `board.cards.ofAgent`  | `GET /v1/agents/{id}/board`                |
| `board.cards.update`   | `PATCH /v1/boards/{id}/cards/{id}`         |
| `board.create`         | `POST /v1/boards`                          |
| `board.get`            | `GET /v1/boards/{id}`                      |

### `computers`

| Method               | Route                              |
| -------------------- | ---------------------------------- |
| `computers.create`   | `POST /v1/computers`               |
| `computers.delete`   | `DELETE /v1/computers/{id}`        |
| `computers.exec`     | `POST /v1/computers/{id}/exec`     |
| `computers.fs`       | `POST /v1/computers/{id}/fs/{id}`  |
| `computers.get`      | `GET /v1/computers/{id}`           |
| `computers.list`     | `GET /v1/computers`                |
| `computers.pause`    | `POST /v1/computers/{id}/pause`    |
| `computers.resume`   | `POST /v1/computers/{id}/resume`   |
| `computers.snapshot` | `POST /v1/computers/{id}/snapshot` |

### `connections`

| Method                         | Route                                      |
| ------------------------------ | ------------------------------------------ |
| `connections.connect`          | `POST /v1/connections`                     |
| `connections.createAuthConfig` | `POST /v1/connections/auth_configs`        |
| `connections.deleteAuthConfig` | `DELETE /v1/connections/auth_configs/{id}` |
| `connections.disconnect`       | `DELETE /v1/connections/{id}`              |
| `connections.get`              | `GET /v1/connections/{id}`                 |
| `connections.getApp`           | `GET /v1/connections/apps/{id}`            |
| `connections.list`             | `GET /v1/connections`                      |
| `connections.listApps`         | `GET /v1/connections/apps`                 |
| `connections.listAuthConfigs`  | `GET /v1/connections/auth_configs`         |

### `credits`

| Method                       | Route                             |
| ---------------------------- | --------------------------------- |
| `credits.billingPortal`      | `POST /v1/credits/billing_portal` |
| `credits.cancelSubscription` | `DELETE /v1/credits/subscription` |
| `credits.ledger`             | `GET /v1/credits/ledger`          |
| `credits.show`               | `GET /v1/credits/balance`         |
| `credits.subscribe`          | `POST /v1/credits/subscription`   |
| `credits.subscription`       | `GET /v1/credits/subscription`    |
| `credits.topup`              | `POST /v1/credits/topups`         |

### `deployments`

| Method               | Route                              |
| -------------------- | ---------------------------------- |
| `deployments.create` | `POST /v1/deployments`             |
| `deployments.delete` | `DELETE /v1/deployments/{id}`      |
| `deployments.get`    | `GET /v1/deployments/{id}`         |
| `deployments.list`   | `GET /v1/deployments`              |
| `deployments.pause`  | `POST /v1/deployments/{id}/pause`  |
| `deployments.resume` | `POST /v1/deployments/{id}/resume` |
| `deployments.run`    | `POST /v1/deployments/{id}/run`    |
| `deployments.runs`   | `GET /v1/deployments/{id}/runs`    |
| `deployments.update` | `PATCH /v1/deployments/{id}`       |

### `domains`

| Method            | Route                          |
| ----------------- | ------------------------------ |
| `domains.create`  | `POST /v1/domains`             |
| `domains.delete`  | `DELETE /v1/domains/{id}`      |
| `domains.get`     | `GET /v1/domains/{id}`         |
| `domains.list`    | `GET /v1/domains`              |
| `domains.records` | `GET /v1/domains/{id}/records` |
| `domains.verify`  | `POST /v1/domains/{id}/verify` |

### `emails`

| Method            | Route                                       |
| ----------------- | ------------------------------------------- |
| `emails.create`   | `POST /v1/identities/{id}/emails`           |
| `emails.delete`   | `DELETE /v1/identities/{id}/emails/{id}`    |
| `emails.list`     | `GET /v1/identities/{id}/emails`            |
| `emails.messages` | `GET /v1/identities/{id}/messages`          |
| `emails.send`     | `POST /v1/identities/{id}/emails/{id}/send` |

### `files`

| Method           | Route                         |
| ---------------- | ----------------------------- |
| `files.delete`   | `DELETE /v1/files/{id}`       |
| `files.download` | `GET /v1/files/{id}`          |
| `files.get`      | `GET /v1/files/{id}`          |
| `files.list`     | `GET /v1/files`               |
| `files.publish`  | `POST /v1/files/{id}/publish` |
| `files.upload`   | `POST /v1/files`              |
| `files.url`      | `POST /v1/files/{id}/url`     |

### `harnesses`

| Method               | Route                    |
| -------------------- | ------------------------ |
| `harnesses.list`     | `GET /v1/harnesses`      |
| `harnesses.retrieve` | `GET /v1/harnesses/{id}` |

### `identities`

| Method                    | Route                                    |
| ------------------------- | ---------------------------------------- |
| `identities.agents`       | `GET /v1/identities/{id}/agents`         |
| `identities.attach`       | `POST /v1/agents/{id}/identities`        |
| `identities.create`       | `POST /v1/identities`                    |
| `identities.delete`       | `DELETE /v1/identities/{id}`             |
| `identities.deleteInbox`  | `DELETE /v1/identities/{id}/emails/{id}` |
| `identities.detach`       | `DELETE /v1/agents/{id}/identities/{id}` |
| `identities.get`          | `GET /v1/identities/{id}`                |
| `identities.held`         | `GET /v1/agents/{id}/identities`         |
| `identities.inboxes`      | `GET /v1/identities/{id}/emails`         |
| `identities.list`         | `GET /v1/identities`                     |
| `identities.messages`     | `GET /v1/identities/{id}/messages`       |
| `identities.phones`       | `GET /v1/identities/{id}/phones`         |
| `identities.releasePhone` | `DELETE /v1/identities/{id}/phones/{id}` |
| `identities.update`       | `PATCH /v1/identities/{id}`              |

### `keys`

| Method        | Route                           |
| ------------- | ------------------------------- |
| `keys.create` | `POST /v1/api_keys`             |
| `keys.list`   | `GET /v1/api_keys`              |
| `keys.revoke` | `DELETE /v1/api_keys/{id}`      |
| `keys.rotate` | `POST /v1/api_keys/{id}/rotate` |

### `media`

| Method             | Route                  |
| ------------------ | ---------------------- |
| `media.listModels` | `GET /v1/media/models` |

### `models`

| Method            | Route                 |
| ----------------- | --------------------- |
| `models.list`     | `GET /v1/models`      |
| `models.retrieve` | `GET /v1/models/{id}` |

### `orgs`

| Method              | Route                                        |
| ------------------- | -------------------------------------------- |
| `orgs.addMember`    | `POST /v1/organizations/{id}/members`        |
| `orgs.create`       | `POST /v1/organizations`                     |
| `orgs.get`          | `GET /v1/organizations/{id}`                 |
| `orgs.list`         | `GET /v1/organizations`                      |
| `orgs.members`      | `GET /v1/organizations/{id}/members`         |
| `orgs.removeMember` | `DELETE /v1/organizations/{id}/members/{id}` |
| `orgs.setRole`      | `PATCH /v1/organizations/{id}/members/{id}`  |
| `orgs.update`       | `PATCH /v1/organizations/{id}`               |

### `phones`

| Method             | Route                                       |
| ------------------ | ------------------------------------------- |
| `phones.list`      | `GET /v1/identities/{id}/phones`            |
| `phones.provision` | `POST /v1/identities/{id}/phones`           |
| `phones.release`   | `DELETE /v1/identities/{id}/phones/{id}`    |
| `phones.send`      | `POST /v1/identities/{id}/phones/{id}/send` |

### `proxy`

| Method              | Route                                       |
| ------------------- | ------------------------------------------- |
| `proxy.completions` | `POST /v1/proxy/openai/v1/chat/completions` |
| `proxy.messages`    | `POST /v1/proxy/anthropic/v1/messages`      |

### `sessions`

| Method                 | Route                                       |
| ---------------------- | ------------------------------------------- |
| `sessions.answer`      | `POST /v1/sessions/{id}/answers`            |
| `sessions.cancel`      | `POST /v1/sessions/{id}/cancel`             |
| `sessions.confirmTool` | `POST /v1/sessions/{id}/tool_confirmations` |
| `sessions.create`      | `POST /v1/sessions`                         |
| `sessions.events`      | `GET /v1/sessions/{id}/events`              |
| `sessions.get`         | `GET /v1/sessions/{id}`                     |
| `sessions.interrupt`   | `POST /v1/sessions/{id}/interrupt`          |
| `sessions.list`        | `GET /v1/sessions`                          |
| `sessions.send`        | `POST /v1/sessions/{id}/messages`           |
| `sessions.setBudget`   | `PATCH /v1/sessions/{id}/budget`            |
| `sessions.threads`     | `GET /v1/sessions/{id}/threads`             |

### `skills`

| Method                | Route                               |
| --------------------- | ----------------------------------- |
| `skills.delete`       | `DELETE /v1/skills/{id}`            |
| `skills.get`          | `GET /v1/skills/{id}`               |
| `skills.getVersion`   | `GET /v1/skills/{id}/versions/{id}` |
| `skills.list`         | `GET /v1/skills`                    |
| `skills.listVersions` | `GET /v1/skills/{id}/versions`      |
| `skills.push`         | `POST /v1/skills`                   |
| `skills.pushVersion`  | `POST /v1/skills/{id}/versions`     |

### `social`

| Method                    | Route                                                    |
| ------------------------- | -------------------------------------------------------- |
| `social.accountAnalytics` | `GET /v1/identities/{id}/social/accounts/{id}/analytics` |
| `social.accounts`         | `GET /v1/identities/{id}/social/accounts`                |
| `social.activate`         | `POST /v1/identities/{id}/social/activate`               |
| `social.comments`         | `GET /v1/identities/{id}/social/posts/{id}/comments`     |
| `social.createPost`       | `POST /v1/identities/{id}/social/posts`                  |
| `social.deletePost`       | `DELETE /v1/identities/{id}/social/posts/{id}`           |
| `social.getPost`          | `GET /v1/identities/{id}/social/posts/{id}`              |
| `social.portal`           | `POST /v1/identities/{id}/social/portal`                 |
| `social.postAnalytics`    | `GET /v1/identities/{id}/social/posts/{id}/analytics`    |
| `social.status`           | `GET /v1/identities/{id}/social`                         |
| `social.upload`           | `POST /v1/identities/{id}/social/uploads`                |

### `stream`

| Method   | Route                          |
| -------- | ------------------------------ |
| `stream` | `GET /v1/sessions/{id}/stream` |

### `vaults`

| Method                      | Route                                     |
| --------------------------- | ----------------------------------------- |
| `vaults.create`             | `POST /v1/vaults`                         |
| `vaults.credentials.create` | `POST /v1/vaults/{id}/credentials`        |
| `vaults.credentials.delete` | `DELETE /v1/vaults/{id}/credentials/{id}` |
| `vaults.credentials.list`   | `GET /v1/vaults/{id}/credentials`         |
| `vaults.delete`             | `DELETE /v1/vaults/{id}`                  |
| `vaults.get`                | `GET /v1/vaults/{id}`                     |
| `vaults.list`               | `GET /v1/vaults`                          |

### `webhooks`

| Method                | Route                                              |
| --------------------- | -------------------------------------------------- |
| `webhooks.create`     | `POST /v1/webhooks`                                |
| `webhooks.delete`     | `DELETE /v1/webhooks/{id}`                         |
| `webhooks.deliveries` | `GET /v1/webhooks/{id}/deliveries`                 |
| `webhooks.delivery`   | `GET /v1/webhooks/{id}/deliveries/{id}`            |
| `webhooks.get`        | `GET /v1/webhooks/{id}`                            |
| `webhooks.list`       | `GET /v1/webhooks`                                 |
| `webhooks.redeliver`  | `POST /v1/webhooks/{id}/deliveries/{id}/redeliver` |
| `webhooks.rotate`     | `POST /v1/webhooks/{id}/rotate`                    |
| `webhooks.test`       | `POST /v1/webhooks/{id}/test`                      |
| `webhooks.update`     | `PATCH /v1/webhooks/{id}`                          |

## Plan

An organization needs an active plan before it can be used. These two methods are open even when it
does not have one, so a client can always read the state and start a checkout.

```ts theme={"system"}
const plan = await client.credits.subscription();
// { object: "subscription", status: "none" | "active" | "past_due" | "canceled",
//   current_period_end, grace_until, cancel_at_period_end, action_url }

if (plan.status !== "active") {
  const { action_url } = await client.credits.subscribe();
  // Send the person to `action_url`. Nothing changes until the signed callback lands.
}
```

Every other call on an organization without a plan answers `402` with code `subscription_required`.
