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

# Overview

The Mesa TypeScript SDK is the ergonomic client for Mesa in Node.js and JavaScript runtimes. It wraps the generated `@mesadev/rest` client, resolves the default organization for you, verifies webhooks, and exposes a native virtual filesystem for repo I/O and shell execution.

Node.js 18 or newer is required.

## Installation

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

## Create a client

```ts theme={null}
import { Mesa } from '@mesadev/sdk';

const mesa = new Mesa({ apiKey: process.env.MESA_API_KEY });

const repos = await mesa.repos.list({ limit: 50 });
console.log(`found ${repos.repos.length} repos`);
```

<Tip>
  Set `MESA_API_KEY` in your environment to omit `apiKey` from the constructor.
</Tip>

## Client options

```ts theme={null}
import { Mesa } from '@mesadev/sdk';

const mesa = new Mesa({
  apiKey: 'mk_...',
  apiUrl: 'https://api.mesa.dev/v1',
  vcsUrl: 'https://vcs.mesa.dev',
  org: 'acme',
  fetch: globalThis.fetch,
  userAgent: 'my-app/1.0.0',
  webhookSecret: 'whsec_...',
});
```

<ParamField path="apiKey" type="string | undefined">
  API key used as a Bearer token — the only credential the client accepts. (Access tokens are signed from it internally; you cannot construct a client from one.) If omitted in Node.js, the SDK reads `MESA_API_KEY` from the environment. Construction throws `MissingCredentialError` if no API key is available.
</ParamField>

<ParamField path="apiUrl" type="string">
  REST API base URL. Defaults to `https://api.mesa.dev/v1`. `http` and `https` are accepted. Trailing slashes are stripped.
</ParamField>

<ParamField path="vcsUrl" type="string">
  VCS service URL used by `mesa.fs.mount(...)`. Defaults to `https://vcs.mesa.dev`. Set this when using a non-default API deployment with MesaFS.
</ParamField>

<ParamField path="org" type="string | undefined">
  Default organization slug. When provided, SDK calls skip `/whoami` for organization resolution.
</ParamField>

<ParamField path="fetch" type="typeof globalThis.fetch | undefined">
  Custom fetch implementation for REST requests.
</ParamField>

<ParamField path="userAgent" type="string | undefined">
  Appended to the SDK user agent. Node.js uses `User-Agent`; browser-like runtimes use `X-Mesa-User-Agent`.
</ParamField>

<ParamField path="webhookSecret" type="string | undefined">
  Signing secret used by `mesa.webhooks.receive(...)`.
</ParamField>

## Lifecycle

The TypeScript client does not hold an HTTP session and does not need to be closed. Reuse one `Mesa` instance where practical.

`mesa.fs.mount(...)` signs one short-lived, scoped access token locally for each mounted filesystem and uses it for the mount's whole lifetime. There is no background refresh and no credential hot-swap: when the token expires the mount stops authenticating, so pass a `ttl` to `mesa.fs.mount(...)` that covers the mount's work (default 1 hour, max 24 hours). Tokens expire on their own, so there is nothing to revoke and no server-side credential is left behind.

## Organization resolution

The SDK chooses an organization in this order:

| Source            | When it applies                                                    |
| ----------------- | ------------------------------------------------------------------ |
| Per-call `org`    | The method input includes `org: '...'`.                            |
| Constructor `org` | The client was created with `new Mesa({ org: '...' })`.            |
| `mesa.whoami()`   | No per-call or constructor org was supplied. The result is cached. |

```ts theme={null}
const mesa = new Mesa({ org: 'acme' });

await mesa.repos.list();
await mesa.repos.list({ org: 'other-org' });
```

## Resource namespaces

| Namespace             | Purpose                                                                                       |
| --------------------- | --------------------------------------------------------------------------------------------- |
| `mesa.repos`          | Create, read, update, delete, sync upstreams, and read upstream sync history on repositories. |
| `mesa.content`        | Read files, symlinks, and directory listings without mounting.                                |
| `mesa.changes`        | Create, patch, and inspect Mesa changes.                                                      |
| `mesa.diffs`          | Inspect diffs and conflicts between changes.                                                  |
| `mesa.bookmarks`      | Manage branch-like bookmark refs.                                                             |
| `mesa.apiKeys`        | Create, list, and revoke Mesa API keys.                                                       |
| `mesa.tokens`         | Sign short-lived, scoped access tokens locally from your API key.                             |
| `mesa.webhookTargets` | Manage outbound webhook targets.                                                              |
| `mesa.webhooks`       | Verify incoming webhook requests and dispatch typed handlers.                                 |
| `mesa.fs`             | Mount repos as a virtual filesystem and run Bash commands.                                    |
| `mesa.org`            | Fetch organization metadata.                                                                  |

Bulk repository tag updates are available through `mesa.raw`.

## Response objects

High-level SDK methods return response data directly. They do not return generated HTTP wrapper objects.

```ts theme={null}
const repos = await mesa.repos.list();
for (const repo of repos.repos) {
  console.log(repo.name, repo.head_change_id);
}
```

Generated response aliases such as `GetRepoResponse` live in `@mesadev/rest`.

## Common types

Import SDK-owned types from `@mesadev/sdk`.

```ts theme={null}
import type { FsMountOptions, MesaOptions, RepoConfig, WebhookEvent } from '@mesadev/sdk';
```

| Type             | Purpose                                                            |
| ---------------- | ------------------------------------------------------------------ |
| `MesaOptions`    | Constructor options for `new Mesa(...)`.                           |
| `FsMountOptions` | Options for `mesa.fs.mount(...)`.                                  |
| `RepoConfig`     | Pin a mounted repo to a bookmark or change.                        |
| `MesaFileSystem` | Native filesystem implementation returned by `mesa.fs.mount(...)`. |
| `ChangeInfo`     | Change metadata returned by mounted filesystem change operations.  |
| `ExecResult`     | Output from `fs.bash().exec(...)`, re-exported from `just-bash`.   |
| `WebhookEvent`   | Discriminated union of webhook event payloads.                     |

High-level REST method input types are inferred from the method signatures. If you need named REST schema types, import them from `@mesadev/rest`.

## Error model

SDK-owned setup and webhook errors extend `MesaError` and expose a stable `code` field.

| Exception                      | Code                          | Meaning                                                                            |
| ------------------------------ | ----------------------------- | ---------------------------------------------------------------------------------- |
| `MissingCredentialError`       | `MISSING_CREDENTIAL`          | No API key was provided, and `MESA_API_KEY` was not available in the environment.  |
| `InvalidApiUrlError`           | `INVALID_API_URL`             | `apiUrl` or `vcsUrl` is malformed or uses a protocol other than `http` or `https`. |
| `InvalidOptionsError`          | `INVALID_OPTIONS`             | Local options are invalid, such as mounting zero repositories.                     |
| `OrgResolutionError`           | `ORG_RESOLUTION_FAILED`       | The SDK could not resolve the default organization through `/whoami`.              |
| `MissingWebhookSecretError`    | `MISSING_WEBHOOK_SECRET`      | `mesa.webhooks.receive(...)` was called without a constructor `webhookSecret`.     |
| `MesaWebhookVerificationError` | `WEBHOOK_VERIFICATION_FAILED` | Webhook signature, timestamp, JSON parsing, or payload validation failed.          |

API operations throw Mesa API error payloads directly when the server returns an error response. These payloads are not `MesaError` instances.

## Raw generated client

`mesa.raw` exposes generated REST operations with authentication, base URL, fetch, and user-agent already wired in. Use it when the high-level SDK does not expose an operation or option yet.

```ts theme={null}
const repo = await mesa.raw.getRepo({
  path: { org: 'acme', repo: 'app' },
});
```

Raw calls use the generated REST request shape (`path`, `query`, `body`) and return response data directly.

## Complete example

```ts theme={null}
import { Buffer } from 'node:buffer';
import { Mesa } from '@mesadev/sdk';

const mesa = new Mesa({ org: 'acme' });

const repo = await mesa.repos.create({ name: 'demo' });

const change = await mesa.changes.create({
  repo: repo.name,
  base_change_id: repo.head_change_id,
  message: 'Add README',
  author: { name: 'Docs Bot', email: 'docs@example.com' },
  files: [
    {
      path: 'README.md',
      content: Buffer.from('# Demo\n').toString('base64'),
    },
  ],
});

await mesa.bookmarks.move({
  repo: repo.name,
  bookmark: repo.default_bookmark,
  change_id: change.id,
});

const fs = await mesa.fs.mount({ repos: [{ name: repo.name }] });
const data = await fs.readFileBuffer(`/acme/${repo.name}/README.md`);
console.log(Buffer.from(data).toString('utf8'));
```
