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

# TypeScript SDK: VrinClient

> Install @vrin/sdk, authenticate, and make your first query from TypeScript, Node, Bun, or the browser.

`@vrin/sdk` is the official TypeScript client. It works in Node 18+, Bun, Deno, Cloudflare Workers, and modern browsers. Written in TypeScript, shipped as both ESM and CJS, fully typed.

If you're building an agent in Python, use the [Python SDK](/sdk/client). If you're shell-scripting, use the [CLI](/cli/overview).

## Install

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

Also works with `pnpm add`, `yarn add`, `bun add`.

## Authenticate

```typescript theme={null}
import { VrinClient } from "@vrin/sdk";

const client = new VrinClient({ apiKey: process.env.VRIN_API_KEY });
```

The API key starts with `vrin_live_` (shared infra) or `vrin_ent_` (enterprise-routed). Get one at [vrin.cloud](https://vrin.cloud) → Dashboard → API Keys.

If `apiKey` is omitted, the client reads `VRIN_API_KEY` from `process.env`.

## First query

```typescript theme={null}
const result = await client.query({ query: "What is ACME's Q4 revenue?" });
console.log(result.summary);
for (const source of result.sources) {
  console.log(` - ${source.title}`);
}
```

## Constructor options

| Option       | Type           | Default                    | Description                                                                                  |
| ------------ | -------------- | -------------------------- | -------------------------------------------------------------------------------------------- |
| `apiKey`     | `string`       | `process.env.VRIN_API_KEY` | Vrin API key.                                                                                |
| `baseUrl`    | `string`       | `https://api.vrin.cloud`   | Override for staging or self-hosted deployments.                                             |
| `timeoutMs`  | `number`       | `120000`                   | Per-request timeout. Must be ≥ the slowest query you expect.                                 |
| `maxRetries` | `number`       | `2`                        | Retry count for transient 5xx/network failures.                                              |
| `fetch`      | `typeof fetch` | global `fetch`             | Inject a custom fetch for runtimes that don't have one (Node \< 18, some edge environments). |

## Usage across runtimes

<Tabs>
  <Tab title="Node 18+">
    ```typescript theme={null}
    import { VrinClient } from "@vrin/sdk";
    const client = new VrinClient({ apiKey: process.env.VRIN_API_KEY });
    ```
  </Tab>

  <Tab title="Bun">
    ```typescript theme={null}
    import { VrinClient } from "@vrin/sdk";
    const client = new VrinClient({ apiKey: Bun.env.VRIN_API_KEY });
    ```
  </Tab>

  <Tab title="Cloudflare Workers">
    ```typescript theme={null}
    import { VrinClient } from "@vrin/sdk";
    export default {
      async fetch(req: Request, env: { VRIN_API_KEY: string }) {
        const client = new VrinClient({ apiKey: env.VRIN_API_KEY });
        const r = await client.query({ query: "..." });
        return Response.json(r);
      },
    };
    ```
  </Tab>

  <Tab title="Browser">
    <Warning>
      Never expose a raw Vrin API key in client-side JavaScript. Proxy through your own backend and call Vrin from there. The browser example below assumes a trusted internal tool context.
    </Warning>

    ```typescript theme={null}
    import { VrinClient } from "@vrin/sdk";
    const client = new VrinClient({ apiKey: "vrin_live_..." });
    ```
  </Tab>
</Tabs>

## Next steps

<CardGroup cols={2}>
  <Card title="Querying" icon="magnifying-glass" href="/sdk-ts/querying">
    `query`, `queryStream`, response modes, depth.
  </Card>

  <Card title="Knowledge" icon="file-arrow-up" href="/sdk-ts/knowledge">
    `insert`, `uploadFile`, polling async jobs.
  </Card>

  <Card title="Conversations" icon="comments" href="/sdk-ts/conversations">
    Multi-turn sessions with `startConversation` + `continueConversation`.
  </Card>

  <Card title="Error handling" icon="triangle-exclamation" href="/sdk-ts/client#error-handling">
    Typed exception hierarchy you can switch on.
  </Card>
</CardGroup>

## Error handling

All errors extend `VrinError`. Import the specific subclasses you want to handle:

```typescript theme={null}
import {
  VrinClient,
  VrinError,
  AuthenticationError,
  RateLimitError,
  ValidationError,
  ServiceUnavailableError,
  TimeoutError,
  InsufficientCoverageError,
} from "@vrin/sdk";

try {
  const r = await client.query({ query: "..." });
} catch (err) {
  if (err instanceof AuthenticationError) {
    // bad key — prompt the user to re-auth
  } else if (err instanceof RateLimitError) {
    // back off; err.retryAfterSeconds is populated if the server sent a Retry-After header
    await sleep((err.retryAfterSeconds ?? 1) * 1000);
  } else if (err instanceof InsufficientCoverageError) {
    // knowledge base has no relevant facts — ingest more or broaden the query
  } else if (err instanceof TimeoutError) {
    // request exceeded timeoutMs — retry with a longer timeout or split the query
  } else if (err instanceof VrinError) {
    console.error("Vrin error:", err.status, err.message);
  } else {
    throw err;
  }
}
```

`VrinError` exposes:

* `message` — human-readable description
* `status?` — HTTP status, when relevant
* `body?` — raw server payload, for logging

## Custom fetch

For runtimes without a global `fetch` (Node 16, some embedded envs) or when you want a middleware-style interceptor:

```typescript theme={null}
import { VrinClient } from "@vrin/sdk";
import { fetch as undiciFetch } from "undici";

const client = new VrinClient({
  apiKey: process.env.VRIN_API_KEY,
  fetch: undiciFetch as unknown as typeof fetch,
});
```
