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

# TypeScript SDK

> Install the Stophy TypeScript SDK, authenticate, call an endpoint, get markdown, page through results, and handle errors and retries.

## Install

```bash theme={null}
npm install stophy
```

The package has no runtime dependencies and ships ESM, CommonJS and type definitions. It runs on Node.js, Bun, Deno and in the browser.

## Authenticate

`apiKey` defaults to the `STOPHY_API_KEY` environment variable, so a bare `new Stophy()` picks it up. Pass a key directly with `new Stophy("your key")` or `new Stophy({ apiKey: "your key" })`.

```ts theme={null}
import { Stophy } from "stophy";

const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY });
```

Without a key, web search, YouTube search and YouTube transcripts still work:

```ts theme={null}
import { Stophy } from "stophy";

const result = await new Stophy().web.search({ query: "bun runtime" });
console.log(result.data.results);
```

Every other endpoint throws `StophyError` with code `unauthorized` and status `401` when called without a key.

## Make a call

```ts theme={null}
import { Stophy } from "stophy";

const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY });

const posts = await stophy.reddit.search({ query: "bun runtime", limit: 10 });
console.log(posts.data, posts.creditsUsed);

const replies = await stophy.youtube.comments.replies({ video: "dQw4w9WgXcQ", cursor: "..." });
console.log(replies.data);
```

Methods follow the endpoint id. Nested ids are nested properties: `youtube.comments.replies` is `stophy.youtube.comments.replies(...)`. Inputs and responses are typed from the [API reference](/api-reference/introduction), so a missing required field is a compile error.

## Get markdown

Pass `{ format: "markdown" }` as the second argument to get a string:

```ts theme={null}
import { Stophy } from "stophy";

const stophy = new Stophy();
const page = await stophy.youtube.search(
  { query: "rust tutorial", limit: 2 },
  { format: "markdown" },
);
console.log(page);
```

## Paging

```ts theme={null}
import { Stophy } from "stophy";

const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY });
let cursor: string | undefined;
do {
  const page = await stophy.reddit.search({ query: "bun runtime", cursor });
  console.log(page.data);
  cursor = page.data.cursor;
} while (cursor);
```

## Find endpoints

```ts theme={null}
import { Stophy } from "stophy";

const catalog = await new Stophy().endpoints();
console.log(catalog.endpoints.length);
```

## Handle errors and retries

```ts theme={null}
import { Stophy, StophyError } from "stophy";

const stophy = new Stophy();

try {
  await stophy.reddit.search({ query: "bun runtime" });
} catch (error) {
  if (error instanceof StophyError) {
    console.log(error.status, error.code, error.message);
    console.log(error.retryable, error.retryAfterSeconds, error.requestId);
  }
}
```

`StophyError` has `status`, `code`, `message`, `retryable`, `retryAfterSeconds` and `requestId`. See [Errors](/api-reference/errors) for every code.

The SDK retries network errors and `429`/`5xx` responses on its own, honoring `Retry-After`, before it throws. Set `maxRetries: 0` to turn that off. `StophyError` only reaches your code after retries are exhausted.

## Options

```ts theme={null}
import { Stophy } from "stophy";

const stophy = new Stophy({
  apiKey: process.env.STOPHY_API_KEY,
  timeoutMs: 20_000,
  maxRetries: 3,
  retryInitialDelayMs: 500,
  headers: { "x-app": "my-app" },
});

const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);
await stophy.web.search({ query: "bun runtime" }, { signal: controller.signal });
```

| Option | Default | What it does |
| - | - | - |
| `apiKey` | `STOPHY_API_KEY` | Your API key. Leave it unset to use the free endpoints. |
| `baseUrl` | `STOPHY_BASE_URL` or `https://api.stophy.dev` | Where requests go |
| `timeoutMs` | `30000` | Timeout for each attempt. A timeout is not retried. |
| `maxRetries` | `2` | Retries for network errors and `429`/`5xx`. `0` turns them off. |
| `retryInitialDelayMs` | `500` | Base backoff delay. Each retry waits longer than the last. |
| `headers` | none | Extra headers on every request |
| `fetch` | global `fetch` | Your own `fetch` |

Per call, pass `{ signal }` to cancel a request and `{ format: "markdown" }` for markdown.

## Usage and logs

These need an API key.

```ts theme={null}
import { Stophy } from "stophy";

const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY });

const usage = await stophy.usage();
console.log(usage.balanceMicros, usage.creditsUsed, usage.requestCount);

const logs = await stophy.logs({ days: 7, page: 0, endpoint: "web.search" });
for (const entry of logs.logs) {
  console.log(entry.createdAt, entry.endpoint, entry.credits);
}
```

`balanceMicros` is your balance in millionths of a dollar: `1000000` is \$1.
