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

# Quickstart

> Install the TypeScript SDK, ingest a video or audio asset, wait for indexing, and run your first scoped search against our media API.

Install the TypeScript SDK, ingest one recording, wait for it to index, and run a search.

## Get an API token

Sign in to the dashboard and open **Settings → API tokens** to create one. New orgs see a one-click onboarding modal that mints a token labeled `default`. The full token is shown once — copy it into a password manager or secrets store before closing the dialog. See [API tokens](https://docs.raidzero.icu/api-tokens.md) for revocation and best practices.

Export the token where the SDK can read it:

```sh theme={null}
export SF_VOICE_API_KEY="sk_live_…"
```

## Install

```sh pnpm theme={null}
pnpm add @sf-voice/media@0.1.1
```

```sh npm theme={null}
npm install @sf-voice/media@0.1.1
```

```sh bun theme={null}
bun add @sf-voice/media@0.1.1
```

## Create a client

```ts theme={null}
import { SfVoiceMedia } from "@sf-voice/media";

const client = new SfVoiceMedia({
  baseUrl: "https://api.sf-voice.com",
  apiKey: process.env.SF_VOICE_API_KEY!,
});
```

## Ingest a recording

Pass your own `asset_id` — this is how you'll identify the recording in search results. Use `asset_class` to group recordings that belong to the same customer or workspace.

```ts theme={null}
const { task_id } = await client.ingest({
  source: "url",
  asset_id: "call_001",
  asset_class: "customer_acme",
  url: "https://example.com/call.mp3",
  media_type: "audio",
  types: ["audio", "transcript"],
});
```

## Wait for indexing

```ts theme={null}
const task = await client.pollTask(task_id, {
  intervalMs: 2_000,
  timeoutMs: 120_000,
});

if (task.status === "failed") {
  throw new Error(task.error ?? "indexing failed");
}
```

## Search

```ts theme={null}
const { results } = await client.search({
  query: "customer asks about pricing",
  asset_class: "customer_acme",
  types: ["transcript"],
  threshold: 0.7,
});

for (const r of results) {
  console.log(r.asset_id, r.start_ms, r.end_ms, r.score);
}
```

Results include `start_ms` and `end_ms` so you can jump a player to the matching segment.

## Full example

```ts theme={null}
import { SfVoiceMedia, SfVoiceMediaError } from "@sf-voice/media";

const client = new SfVoiceMedia({
  baseUrl: "https://api.sf-voice.com",
  apiKey: process.env.SF_VOICE_API_KEY!,
});

try {
  const { task_id } = await client.ingest({
    source: "url",
    asset_id: "call_001",
    asset_class: "customer_acme",
    url: "https://example.com/call.mp3",
    media_type: "audio",
    types: ["audio", "transcript"],
  });

  const task = await client.pollTask(task_id);

  if (task.status === "failed") {
    throw new Error(task.error ?? "indexing failed");
  }

  const { results } = await client.search({
    query: "customer asks about pricing",
    asset_class: "customer_acme",
  });

  console.log(results);
} catch (err) {
  if (err instanceof SfVoiceMediaError) {
    console.error(err.code, err.status, err.message);
  }
  throw err;
}
```

## Next steps

> [card] [How it works](https://docs.raidzero.icu/how-it-works.md)
>
> Understand the ingest → index → search lifecycle.

> [card] [TypeScript SDK](https://docs.raidzero.icu/sdks/typescript.md)
>
> Inputs, outputs, and error types.


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