> ## Documentation Index
> Fetch the complete documentation index at: https://docs.icelab.sh/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.

## Install

<CodeGroup>
  ```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
  ```
</CodeGroup>

## 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

<CardGroup cols={2}>
  <Card title="How it works" icon="workflow" href="/how-it-works">
    Understand the ingest → index → search lifecycle.
  </Card>

  <Card title="TypeScript SDK" icon="square-js" href="/sdks/typescript">
    Inputs, outputs, and error types.
  </Card>
</CardGroup>
