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

# Search llms-full.txt

> Complete machine-readable documentation content for Search (AI) for AI agents and LLMs

# Telnyx AI: Search — Full Documentation

> Complete page content for Search (AI section) of the Telnyx developer docs ([https://developers.telnyx.com](https://developers.telnyx.com)).
> This file: [https://developers.telnyx.com/development/llms/ai-search-llms-full-txt.md](https://developers.telnyx.com/development/llms/ai-search-llms-full-txt.md) · Root index: [https://developers.telnyx.com/llms.txt](https://developers.telnyx.com/llms.txt)

## Search

### Overview

> Source: [https://developers.telnyx.com/docs/ai-search.md](https://developers.telnyx.com/docs/ai-search.md)

Search is a managed search service over the data your Telnyx account already holds. Create a **collection**, attach sources, and query them with natural language through one retrieval API. Telnyx handles embedding, indexing, and ranking. Voice call transcriptions are searchable today; meetings, messaging, and stored documents are coming soon.

It is retrieval-only by design: every search returns scored, source-attributed chunks ready to ground any LLM. Generation belongs to your application -- bring your own model.

## How It Works

1. **[Create a collection](/docs/ai-search/manage-collections)** -- a named container with retrieval settings. Creating one is instant: a collection is a pointer, not a copy.
2. **[Attach sources](/docs/ai-search/sources)** -- mix voice, meeting, messaging, and bucket sources in one collection.
3. **[Configure settings](/docs/ai-search/settings)** -- retrieval mode and result count, with per-request overrides.
4. **[Search](/docs/ai-search/searching)** -- one `GET` returns ranked chunks with scores, metadata, and source attribution.

For the pipeline behind this -- and how Search relates to the lower-level embeddings APIs -- see [How Search Works](/docs/ai-search/how-it-works).

## Sources

A collection can include any combination of these source types:

| Source type                              | What it indexes                             |
| ---------------------------------------- | ------------------------------------------- |
| [`voice`](/docs/ai-search/sources/voice) | Voice call transcriptions for the account   |
| `meeting_bot` Coming soon                | Meeting transcriptions for the account      |
| `message` Coming soon                    | Messaging history for the account           |
| `bucket` Coming soon                     | Files in one specific Telnyx Storage bucket |

Conversation-backed sources index what [conversation persistence](/docs/ai-search/sources/voice) has stored for the account -- new calls become searchable minutes after they end.

## Next Steps

First collection to first search in a few minutes.
Indexing, querying, and what a collection actually is.
Vector, keyword, and hybrid retrieval compared.
The retrieval call: parameters, filters, pagination, errors.

***

### Get Started

> Source: [https://developers.telnyx.com/docs/ai-search/get-started.md](https://developers.telnyx.com/docs/ai-search/get-started.md)

Create a collection, attach your voice call transcriptions as a source, and search them with natural language. This quickstart uses the REST API -- every step is a copy-paste request.

## Prerequisites

* A Telnyx API key from the [portal](https://portal.telnyx.com/#/api-keys). Export it so the examples work as-is:

```bash theme={null}
export TELNYX_API_KEY="KEY..."
```

* Content to search. The `voice` source indexes your account's persisted voice call transcriptions -- see [how to enable persistence](/docs/ai-search/sources/voice). An account with no persisted transcriptions returns empty results, but the API calls below still work.

A collection is a named search index. `name` is required; everything else has defaults.

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/ai/collections \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support search",
    "description": "Searchable support call transcripts"
  }'
```

```json theme={null}
{
  "data": {
    "uuid": "fc96a26f-c4a1-484e-afc4-d94b903778cc",
    "slug": "support-search",
    "record_type": "ai_collection",
    "name": "Support search",
    "description": "Searchable support call transcripts",
    "status": "ready",
    "sources": [],
    "settings": { "retrieval": { "top_k": 5, "retrieval_type": "vector" } },
    "created_at": "2026-08-07T14:56:55.558737Z",
    "updated_at": "2026-08-07T14:56:55.558737Z"
  }
}
```

Two identifiers come back: the `uuid` (used by the management API) and the `slug`, derived from `name` (used by the search API). Default settings apply -- `top_k: 5`, `retrieval_type: vector`. The collection has no sources yet, so there is nothing to search.

Add the `voice` source -- your account's call transcriptions:

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/ai/collections/fc96a26f-c4a1-484e-afc4-d94b903778cc/sources \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "source_type": "voice" }'
```

```json theme={null}
{
  "data": {
    "id": "source_8vkvtcksnawvbnxq48yv2l06wx",
    "record_type": "ai_collection_source",
    "collection_id": "fc96a26f-c4a1-484e-afc4-d94b903778cc",
    "source_type": "voice",
    "status": "ready"
  }
}
```

The source is `ready` and its content is indexed for search. More source types are coming soon -- see [Sources](/docs/ai-search/sources).

Search is a `GET` on the collection's documents, addressed by slug:

```bash theme={null}
curl -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/support-search/documents?query=did+we+promise+a+refund"
```

```json theme={null}
{
  "data": [
    {
      "id": "e30570b6-68d5-11f1-838c-02420a0ddb20:0",
      "record_id": "e30570b6-68d5-11f1-838c-02420a0ddb20",
      "chunk_index": 0,
      "chunk_total": 1,
      "text": "...The refund of $200 has been deposited back in your account...",
      "score": 0.904,
      "record_type": "voice",
      "region": "USA",
      "record_created_at": "2026-06-15T16:18:49.981698+00:00",
      "ingested_at": "2026-06-15T16:20:12.170251+00:00",
      "metadata": { "source": "Trunking" }
    }
  ],
  "meta": {
    "collection_slug": "support-search",
    "searched_sources": ["voice"],
    "retrieval_type": "vector",
    "top_k": 5,
    "total_results": 56,
    "total_pages": 12,
    "page_number": 1,
    "page_size": 5
  }
}
```

Each result is a scored chunk that says what it is and where it came from -- `record_id`, `record_type`, timestamps, and `metadata`. The match works on meaning, not exact words: "did we promise a refund" finds "the refund has been deposited".

Per-request parameters override the collection defaults for that one request:

```bash theme={null}
# Fewer results and a date filter (--globoff: the [ ] are literal)
curl --globoff -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/support-search/documents?query=refund&top_k=3&filter[record_created_at][gte]=2026-06-01T00:00:00Z"
```

See [Search](/docs/ai-search/searching) for the full parameter and filter reference.

The search response is grounding, ready to hand to any LLM as tool output -- Search never generates answers itself. Declare the search call as a function tool, run it when the model asks, and feed the chunks back.

## Next Steps

The indexing and query pipelines, and what a collection actually is.
Attach sources and enable the data behind them.
Configure retrieval mode and result count per collection.
Filters, pagination, document reassembly, and errors.

***

### Search

> Source: [https://developers.telnyx.com/docs/ai-search/searching.md](https://developers.telnyx.com/docs/ai-search/searching.md)

Search is the retrieval call that ranks a collection's documents by relevance to a query. It lives at the documents sub-resource -- a `GET` on the collection's documents with the query as a filter.

## Shape

Search is a `GET` on the documents sub-resource with the query as a query parameter. With no query it's a plain date-sorted catalog listing; with a query it's a ranked `vector` retrieval (`hybrid` and `keyword` are [coming soon](/docs/ai-search/search-modes)). The collection is addressed by `slug` (customer-facing), not `uuid`.

| Method | Path                                            | Purpose                                |
| ------ | ----------------------------------------------- | -------------------------------------- |
| `GET`  | `/v2/ai/collections/&#123;slug&#125;/documents` | Search / list a collection's documents |

A collection with no searchable sources returns `422` (see [Errors](#errors)).

## Basic vs Advanced

A search can be as simple as a plain natural-language question, or as rich as a source-scoped, filtered, paginated retrieval call. Choose the tab that matches how much control you need.

A basic search sends only the `query`. The collection's settings decide how many results come back (`top_k`, default 5) and how they are ranked (`retrieval_type`).

```bash theme={null}
# Basic ranked search
curl -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/support-search/documents?query=did+we+promise+Acme+a+refund"
```

```json theme={null}
{
  "data": [
    {
      "id": "chunk_abc",
      "record_id": "rec_123",
      "chunk_index": 2,
      "chunk_total": 9,
      "text": "...full refund within 5 business days...",
      "score": 0.87,
      "record_type": "voice",
      "region": "USA",
      "record_created_at": "2026-07-10T12:15:00Z",
      "ingested_at": "2026-07-10T12:16:04Z",
      "metadata": { "call_id": "call-100" }
    }
  ],
  "meta": {
    "collection_slug": "support-search",
    "searched_sources": ["voice"],
    "retrieval_type": "vector",
    "top_k": 5,
    "total_results": 5,
    "total_pages": 1,
    "page_number": 1,
    "page_size": 5
  }
}
```

An advanced search stacks `top_k`, `sources`, `filter[field][op]`, and pagination on top of the `query`.

### Query Parameters

| Param                         | Required | Meaning                                                                                                                                                             |
| ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`                       | optional | Relevance query. Omitted -> catalog listing (date desc). Present -> relevance-ranked.                                                                               |
| `top_k`                       | optional | Override the collection default. 1--50; values outside the range are rejected with `422`.                                                                           |
| `sources`                     | optional | Narrow to a subset of the collection's source types (e.g. `voice`), comma-separated.                                                                                |
| `filter[field][op]`           | optional | Field filtering (the same `filter[field][op]=value` system described below).                                                                                        |
| `page[number]` / `page[size]` | optional | Telnyx bracket pagination.                                                                                                                                          |
| `retrieval_type`              | optional | Reserved for `hybrid` and `keyword` ([coming soon](/docs/ai-search/search-modes)). Searches run `vector` retrieval; `meta.retrieval_type` echoes the mode that ran. |

### Field Filters

The same `filter[field][op]=value` system the search/documents endpoints already use. Operators: `eq`, `in`, `gte`, `gt`, `lte`, `lt`, `contains`. Multiple filters AND together.

Known top-level fields: `record_type`, `record_id`, `user_id`, `record_created_at`, `ingested_at`, plus any other name -> a `metadata.*` filter (pass the bare key, e.g. `filter[call_id]=...`). `region` and `score` are not filterable -> `400`.

For vector search the filter is applied pre-kNN, so it narrows candidates without distorting scores.

### Advanced Example

```bash theme={null}
# Narrow to one source + a metadata filter (bare key). --globoff: the [ ] are literal.
curl --globoff -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/support-search/documents?query=refund&sources=voice&filter[call_id]=call-100"
```

## Reconstructing a Document

Search and listing share one endpoint -- the presence of `query` decides the behavior. Omit `query` to get a plain, date-ordered listing instead of a ranked search.

During indexing, a transcription or file is split into multiple chunks. To retrieve every chunk that belongs to a single record -- for example to reassemble one full transcript -- omit `query` and filter by `record_id`:

```bash theme={null}
# List all chunks of one document (no query -> not ranked, not billed as a search).
# top_k governs how many chunks are returned; set it high enough to cover chunk_total.
# --globoff is required so curl does not treat the [ ] in filter/page keys as globs.
curl --globoff -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/support-search/documents?filter[record_id][eq]=rec_123&top_k=50&page[size]=50"
```

```json theme={null}
{
  "data": [
    { "id": "chunk_0", "record_id": "rec_123", "chunk_index": 0, "chunk_total": 3,
      "text": "Customer opened the call asking about...", "record_type": "voice" },
    { "id": "chunk_1", "record_id": "rec_123", "chunk_index": 1, "chunk_total": 3,
      "text": "...we agreed to a full refund within 5 business days...", "record_type": "voice" },
    { "id": "chunk_2", "record_id": "rec_123", "chunk_index": 2, "chunk_total": 3,
      "text": "...confirmed the mailing address before ending the call.", "record_type": "voice" }
  ],
  "meta": {
    "collection_slug": "support-search",
    "searched_sources": ["voice"],
    "top_k": 50,
    "total_results": 3,
    "total_pages": 1,
    "page_number": 1,
    "page_size": 50
  }
}
```

Without a `query`, results come back in date order rather than by relevance score, and the request is **not** billed as a search event. Each chunk carries `chunk_index` and `chunk_total`, so you can order the chunks (`chunk_index` ascending) and reassemble the complete document text.

Because a collection's sources can be stored across multiple regions, a fan-out search may return the same chunk once per region (duplicate `id` values with different `region` values). Deduplicate by `id` before sorting by `chunk_index`, otherwise reassembled text repeats sections.

`page[size]` is echoed in the response `meta` but does not limit how many chunks are returned -- `top_k` governs the array length. To retrieve every chunk of a record, set `top_k` high enough to cover `chunk_total` (up to the maximum of 50) rather than relying on pagination.

When copying `curl` examples that use bracketed keys like `filter[...]` or `page[...]`, pass `--globoff` (curl otherwise treats `[` and `]` as glob/range syntax and the request fails before it is sent).

## Errors

Search errors are returned in the standard Telnyx error envelope with a numeric code:

```json theme={null}
// 404 -- no collection with that slug
{
  "errors": [{
    "code": "10005",
    "title": "Resource not found",
    "detail": "The requested resource or URL could not be found.",
    "meta": { "url": "https://developers.telnyx.com/docs/overview/errors/10005" }
  }]
}

// 422 -- the request cannot be processed, for example a collection with no
// searchable sources, or top_k outside 1-50
{
  "errors": [{
    "code": "10027",
    "title": "Unprocessable Entity",
    "detail": "The server understood the syntax of the request but was unable to process the instructions.",
    "meta": { "url": "https://developers.telnyx.com/docs/overview/errors/10027" }
  }]
}
```

A `400` is returned for malformed requests -- for example filtering on a non-filterable field such as `region` or `score`.

## Billing

Each ranked search (a request with a `query` parameter) counts as one billable search event. Browsing a collection's documents without a query (catalog listing) is free. See [Pricing](/docs/inference/embedding-rag/pricing) for rates.

***

## Concepts

### How Search Works

> Source: [https://developers.telnyx.com/docs/ai-search/how-it-works.md](https://developers.telnyx.com/docs/ai-search/how-it-works.md)

Search has two core processes: **indexing**, which turns your content into searchable chunks continuously in the background, and **querying**, which retrieves the most relevant chunks for a request. Understanding both explains why collections are cheap to create and why search results look the way they do.

## How Indexing Works

Each source system owns its own ingestion -- content becomes searchable without any per-collection work:

1. **Ingest** -- a data source is enabled for indexing. Voice transcriptions flow in as calls end, controlled by [conversation persistence](/docs/ai-search/sources/voice) -- a collection can only see what persistence has stored for the account.
2. **Chunk** -- each record (a transcript, a file) is split into chunks sized for retrieval. Chunks carry `chunk_index` and `chunk_total` so a full record can be [reassembled](/docs/ai-search/searching#reconstructing-a-document) later.
3. **Embed** -- each chunk is converted into a vector that captures its meaning, and stored in the source's vector database alongside its metadata (`record_id`, timestamps, origin fields).

New calls are searchable minutes after they end. There are no sync schedules to manage.

## How Querying Works

When you search a collection:

1. **Resolve the collection** -- the collection's [sources](/docs/ai-search/sources) and [settings](/docs/ai-search/settings) are looked up by slug; per-request parameters override settings for that request only.
2. **Embed the query** -- the query text is embedded with the same model family used at indexing time.
3. **Filter** -- any [`filter[field][op]`](/docs/ai-search/searching#field-filters) conditions are applied before nearest-neighbor search, so filters narrow the candidate set without distorting scores.
4. **Fan out** -- the search runs against every searchable source in the collection, across all regions where content is stored.
5. **Merge** -- per-source, per-region results are merged into one list ranked by relevance `score`, capped at `top_k`.
6. **Return chunks** -- each chunk carries its text, score, and source metadata. Search stops here by design: generation belongs to your application.

The whole fan-out counts as **one** billable search event, regardless of how many sources and regions were searched. See [Pricing](/docs/inference/embedding-rag/pricing).

## A Collection Is a Pointer

Creating a collection only writes configuration rows -- it does not copy, move, or re-embed content. This has practical consequences:

* Creation is instant, and a new collection over already-indexed sources is immediately searchable.
* Removing a source or deleting a collection drops only collection-scoped artifacts. The underlying Telnyx data is never modified or deleted.
* The same source can back many collections at no extra indexing cost.

## Search vs. the Embeddings APIs

Telnyx also ships lower-level building blocks -- the [Embeddings API](/docs/inference/embeddings) embeds documents in a Storage bucket, and `POST /v2/ai/embeddings/similarity-search` queries one bucket directly. Search is the managed layer above them:

|                  | Search                                              | Embeddings API                                                                              |
| ---------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| What it is       | Managed search product over your Telnyx data        | Bucket-level embedding primitives you compose yourself                                      |
| You give it      | Sources (`voice` today, more coming soon)           | One Storage bucket per request                                                              |
| Scope of a query | Every source in the collection, merged and ranked   | A single embedded bucket                                                                    |
| Ingestion        | Continuous, owned by each source system             | You trigger embedding per bucket                                                            |
| Query surface    | `GET /v2/ai/collections/&#123;slug&#125;/documents` | `POST /v2/ai/embeddings/similarity-search`                                                  |
| Grounded chat    | Bring your own LLM over search results              | `retrieval` tool on [chat completions](/docs/inference/embeddings#chat-over-your-documents) |
| Best when        | Searching your account's conversations              | You need direct control of one bucket's embeddings                                          |

If you are starting fresh, start with Search. Reach for the embeddings APIs when you need the primitive itself.

***

### Search Modes

> Source: [https://developers.telnyx.com/docs/ai-search/search-modes.md](https://developers.telnyx.com/docs/ai-search/search-modes.md)

A collection's `retrieval_type` selects how queries are matched against indexed content. There are three modes. To see how each behaves, take one query a support team might run: **"error 10015 on outbound call"**.

## Vector

Available

The query is embedded into a vector and compared against indexed chunks by nearest-neighbor similarity. It matches on **meaning**, so wording can differ: "did we agree to a refund?" finds "we'll credit the invoice".

For the example query, vector search understands the *concept* -- call failures, error handling -- and finds transcripts about failing outbound calls. Its blind spot is the literal string: the chunk containing exactly `10015` may not rank first, because digits have weak semantic neighbors.

Best for natural-language questions where exact terms vary. This is the default mode.

## Keyword

Coming soon

Classic lexical search (BM25) -- term-frequency ranking over the actual words, no embeddings. It matches on **exact tokens**, so it finds the chunk that literally contains `10015`. Its blind spot is paraphrase: a transcript that says "the call was rejected with a billing error" but never says "10015" is invisible to it.

Best for identifiers, error codes, SKUs, and names.

## Hybrid

Coming soon

Runs vector and keyword in parallel and fuses the two result sets into one ranking. For the example query it finds both the transcript with the literal `10015` and the ones that only describe the failure -- semantic recall plus exact-term precision in a single call, at the cost of slightly more work per request.

Best when queries are mixed or unpredictable.

***

## Configuration

### Collections

> Source: [https://developers.telnyx.com/docs/ai-search/manage-collections.md](https://developers.telnyx.com/docs/ai-search/manage-collections.md)

A **collection** is the core resource in Search -- a named container for data sources with its own retrieval settings. This page covers the full CRUD lifecycle. [Sources](/docs/ai-search/sources) and [Settings](/docs/ai-search/settings) have their own subresources, documented separately.

Management operations address a collection by `uuid`; [search](/docs/ai-search/searching) addresses it by `slug`.

## Create a Collection

`name` is required. `slug` is derived from `name` when omitted and must be unique per organization. A collection may be created with or without initial `sources`. `settings` is optional -- defaults apply (`top_k = 5`, `retrieval_type = vector`).

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/ai/collections \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Collections for personal calls",
    "description": "Searchable personal call transcripts",
    "sources": [
      { "source_type": "voice" }
    ],
    "settings": {
      "retrieval": { "top_k": 10, "retrieval_type": "vector" }
    }
  }'
```

```json theme={null}
{
  "data": {
    "uuid": "b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a",
    "slug": "collections-personal-calls",
    "record_type": "ai_collection",
    "name": "Collections for personal calls",
    "description": "Searchable personal call transcripts",
    "status": "ready",
    "sources": [
      { "id": "source_8vkvtcksnawvbnxq48yv2l06wx", "record_type": "ai_collection_source",
        "collection_id": "b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a",
        "source_type": "voice", "status": "ready" }
    ],
    "settings": { "retrieval": { "top_k": 10, "retrieval_type": "vector" } },
    "created_at": "2026-08-07T14:56:55.558737Z",
    "updated_at": "2026-08-07T14:56:55.558737Z"
  }
}
```

Returns `201 Created` with the full collection record.

### Slug Conflicts

If a collection with the same slug already exists for the account, the request returns `409 Conflict`:

```json theme={null}
{
  "errors": [{
    "code": "collection_slug_taken",
    "title": "Collection slug already in use",
    "detail": "A collection with slug 'collections-personal-calls' already exists for this account.",
    "source": { "pointer": "/slug" }
  }]
}
```

## List Collections

```bash theme={null}
curl -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections"
```

Returns `200 OK` with the Telnyx V2 `data` + `meta` envelope -- each item is a full collection record:

```json theme={null}
{
  "data": [
    {
      "uuid": "b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a",
      "slug": "collections-personal-calls",
      "record_type": "ai_collection",
      "name": "Collections for personal calls",
      "description": "Searchable personal call transcripts",
      "status": "ready",
      "sources": [
        { "id": "source_8vkvtcksnawvbnxq48yv2l06wx", "record_type": "ai_collection_source",
          "collection_id": "b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a",
          "source_type": "voice", "status": "ready" }
      ],
      "settings": { "retrieval": { "top_k": 10, "retrieval_type": "vector" } },
      "created_at": "2026-08-07T14:56:55.558737Z",
      "updated_at": "2026-08-07T14:56:55.558737Z"
    }
  ],
  "meta": { "total_pages": 1, "total_results": 1, "page_number": 1, "page_size": 20 }
}
```

### Pagination

Pagination is optional. Use `page[number]`/`page[size]` query parameters (default size 20, max 100). Results are sorted by `slug` then `created_at`.

```bash theme={null}
# Second page (--globoff so curl does not treat [ ] as globs)
curl --globoff -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections?page[number]=2&page[size]=20"
```

## Retrieve a Collection by UUID

Lookup by UUID returns the full collection record.

```bash theme={null}
curl -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a"
```

If no collection exists with that UUID for the account, the request returns `404 Not Found`.

## Retrieve a Collection by Slug

Lookup by slug returns the same full record. Slugs are unique per organization.

```bash theme={null}
curl -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/slug/collections-personal-calls"
```

If no collection exists with that slug for the account, the request returns `404 Not Found`.

## Update Collection Metadata

`PATCH` updates metadata only (`name`, `description`). Partial -- omitted fields are untouched. `slug` is immutable; renaming does not regenerate it. Sources and settings have their own subresources.

```bash theme={null}
curl -X PATCH https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer Conversation Intelligence",
    "description": "Calls and meetings used by the support AI"
  }'
```

Returns the full updated collection record with a refreshed `updated_at`. Slug is unchanged.

Add, replace, and remove data sources.
Configure retrieval type and top\_k.

## Delete a Collection

Soft delete. Sets `deleted_at` and `status = deleted`, then excludes the collection from list results and returns `404` on detail lookups. The slug is freed for reuse immediately.

No external data is touched -- transcriptions, embeddings, and credential connections are not affected. Deleting an already-deleted or unknown collection returns `404`.

```bash theme={null}
curl -X DELETE -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a"
```

Returns `204 No Content` -- no body.

## Related

* [Get started](/docs/ai-search/get-started) -- first collection to first search
* [Sources](/docs/ai-search/sources) -- add, replace, and remove data sources
* [Settings](/docs/ai-search/settings) -- configure retrieval type and top\_k
* [Search](/docs/ai-search/searching) -- query a collection's documents

***

### Overview

> Source: [https://developers.telnyx.com/docs/ai-search/sources.md](https://developers.telnyx.com/docs/ai-search/sources.md)

Sources are the data inputs a collection searches across. Each source type has its own page covering what it indexes and how to enable the underlying data:

| Source type                              | What it indexes                             |
| ---------------------------------------- | ------------------------------------------- |
| [`voice`](/docs/ai-search/sources/voice) | Voice call transcriptions for the account   |
| `meeting_bot` Coming soon                | Meeting transcriptions for the account      |
| `message` Coming soon                    | Messaging history for the account           |
| `bucket` Coming soon                     | Files in one specific Telnyx Storage bucket |

Sources are managed through dedicated endpoints -- never through collection `PATCH` (which would be ambiguous about intent). When a source is added, the resource is created with `status` set to `ready` and its content is indexed for search.

## Add One Source

`POST /v2/ai/collections/&#123;uuid&#125;/sources` adds a single source without touching the others.

```bash theme={null}
# Add a voice source
curl -X POST https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a/sources \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "source_type": "voice" }'
```

```json theme={null}
{
  "data": {
    "id": "source_8vkvtcksnawvbnxq48yv2l06wx",
    "record_type": "ai_collection_source",
    "collection_id": "b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a",
    "source_type": "voice",
    "status": "ready"
  }
}
```

Returns `201 Created` with the new source object.

## Replace All Sources

`PUT /v2/ai/collections/&#123;uuid&#125;/sources` replaces the complete source list. The server reconciles by logical identity:

* `voice` -- by `source_type`

Retained sources are not reindexed. Dropped sources are detached from this collection only -- replacing the list never starts physical cleanup of chunks, embeddings, or metadata, and never deletes the underlying Telnyx product data.

```bash theme={null}
curl -X PUT https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a/sources \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sources": [
      { "source_type": "voice" }
    ]
  }'
```

```json theme={null}
{
  "data": [
    { "id": "source_8vkvtcksnawvbnxq48yv2l06wx", "record_type": "ai_collection_source",
      "collection_id": "b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a", "source_type": "voice", "status": "ready" }
  ],
  "meta": {
    "added":    [],
    "retained": [ "source_8vkvtcksnawvbnxq48yv2l06wx" ],
    "removed":  [ "source_8atnodb2vjqlpqwm211lwo739w" ]
  }
}
```

## List Sources

```bash theme={null}
curl -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a/sources"
```

```json theme={null}
{
  "data": [
    { "id": "source_8vkvtcksnawvbnxq48yv2l06wx", "record_type": "ai_collection_source",
      "collection_id": "b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a",
      "source_type": "voice", "status": "ready" }
  ]
}
```

## Remove One Source

`DELETE /v2/ai/collections/&#123;uuid&#125;/sources/&#123;source_id&#125;` removes a single source; the rest are untouched. Excluded from new searches immediately -- this detaches the collection's pointer to the source only.

A source can back many collections, so detaching never starts physical cleanup of chunks, embeddings, or metadata. Never deletes the original Telnyx product data. Never disables a bucket or credential connection.

```bash theme={null}
curl -X DELETE -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a/sources/source_8vkvtcksnawvbnxq48yv2l06wx"
```

Returns `204 No Content` -- no body.

## Related

* [Collections](/docs/ai-search/manage-collections) -- create, list, retrieve, update, and delete collections
* [Settings](/docs/ai-search/settings) -- configure retrieval type and top\_k

***

### Voice

> Source: [https://developers.telnyx.com/docs/ai-search/sources/voice.md](https://developers.telnyx.com/docs/ai-search/sources/voice.md)

The `voice` source indexes your account's persisted voice call transcriptions. Calls become searchable minutes after they end -- there is nothing to sync.

## Attach the Source

```bash theme={null}
curl -X POST https://api.telnyx.com/v2/ai/collections/{uuid}/sources \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "source_type": "voice" }'
```

The source indexes every persisted voice transcription on the account. A collection over an account with no persisted transcriptions returns empty results -- enable persistence first.

## Enable Voice Transcript Persistence

Voice transcripts are persisted per SIP connection. Set `conversation_persistence` to `true` on each connection whose calls you want transcribed, stored, and indexed:

```bash theme={null}
curl -X PATCH https://api.telnyx.com/v2/credential_connections/{id} \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "conversation_persistence": true }'
```

The same field exists on all supported connection types:

| Connection type        | Endpoint                                          |
| ---------------------- | ------------------------------------------------- |
| Credential connections | `PATCH /v2/credential_connections/&#123;id&#125;` |
| IP connections         | `PATCH /v2/ip_connections/&#123;id&#125;`         |
| FQDN connections       | `PATCH /v2/fqdn_connections/&#123;id&#125;`       |

Verify with a `GET` on the connection -- the response includes `conversation_persistence`. Set it to `false` to stop persisting new calls.

From then on, every call handled by that connection is transcribed and indexed automatically. Persisted records include 30 days of indexed retention -- see [Pricing](/docs/inference/embedding-rag/pricing) for extended retention.

## What a Result Looks Like

Voice chunks carry `record_type: "voice"` plus the call's identifiers and timestamps:

```json theme={null}
{
  "id": "e30570b6-68d5-11f1-838c-02420a0ddb20:0",
  "record_id": "e30570b6-68d5-11f1-838c-02420a0ddb20",
  "chunk_index": 0,
  "chunk_total": 1,
  "text": "...The refund of $200 has been deposited back in your account...",
  "score": 0.904,
  "record_type": "voice",
  "record_created_at": "2026-06-15T16:18:49.981698+00:00",
  "ingested_at": "2026-06-15T16:20:12.170251+00:00",
  "metadata": { "source": "Trunking" }
}
```

Narrow searches to calls with `sources=voice` or filter on record fields -- see [Search](/docs/ai-search/searching).

***

### Settings

> Source: [https://developers.telnyx.com/docs/ai-search/settings.md](https://developers.telnyx.com/docs/ai-search/settings.md)

Settings hold the collection's default retrieval configuration in their own subresource -- collection `PATCH` never touches them. Settings are accessed at `/v2/ai/collections/&#123;uuid&#125;/settings`, and any setting can be overridden per request at [search](/docs/ai-search/searching) time.

| Field            | Type    | Values                                        | Default  |
| ---------------- | ------- | --------------------------------------------- | -------- |
| `top_k`          | integer | 1--50                                         | 5        |
| `retrieval_type` | string  | `vector` (`hybrid` and `keyword` coming soon) | `vector` |

`retrieval_type` selects how a query is matched against the collection's indexed content -- see [Search Modes](/docs/ai-search/search-modes) for how the modes differ and when to use each.

`hybrid` and `keyword` retrieval are coming soon. Keep `retrieval_type` set to `vector` -- a collection set to `hybrid` cannot be searched yet.

## Get Settings

```bash theme={null}
curl -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a/settings"
```

```json theme={null}
{
  "data": {
    "record_type": "ai_collection_settings",
    "retrieval": { "top_k": 5, "retrieval_type": "vector" }
  }
}
```

## Replace Settings

`PUT` replaces the entire settings object. Omitted keys reset to their defaults.

```bash theme={null}
curl -X PUT https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a/settings \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "retrieval": { "top_k": 25, "retrieval_type": "vector" } }'
```

## Merge Settings

`PATCH` does a partial merge at the `retrieval` key. Unnamed fields are preserved.

```bash theme={null}
curl -X PATCH https://api.telnyx.com/v2/ai/collections/b3b1c8a2-9f4e-4d2a-9c1e-2f7a6d5b4c3a/settings \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "retrieval": { "top_k": 5 } }'
```

Returns the full merged settings object -- `retrieval_type` is unchanged.

## Validation Errors

Unsupported `retrieval_type` values return `422`:

```json theme={null}
{
  "errors": [{
    "code": "unsupported_retrieval_type",
    "title": "Unsupported retrieval type",
    "detail": "retrieval_type 'semantic' is not supported. Supported types: 'hybrid', 'vector'.",
    "source": { "pointer": "/retrieval/retrieval_type" }
  }]
}
```

`top_k` outside 1--50 returns `422` with code `invalid_top_k`. Unrecognized fields in the `retrieval` object are rejected with `400`.

## Related

* [Search Modes](/docs/ai-search/search-modes) -- vector, keyword, and hybrid compared
* [Collections](/docs/ai-search/manage-collections) -- create, list, retrieve, update, and delete collections
* [Sources](/docs/ai-search/sources) -- add, replace, and remove data sources

***

## API Reference (Search)

### AI Collections

* [Create a collection](https://developers.telnyx.com/api-reference/ai-collections/create-a-collection.md): Creates a new collection scoped to your organization. Optionally attach sources and retrieval settings at creation time. If `slug` is omitted, one is derived f…
* [List collections](https://developers.telnyx.com/api-reference/ai-collections/list-collections.md): Returns a paginated list of collections in your organization.
* [Get a collection by slug](https://developers.telnyx.com/api-reference/ai-collections/get-a-collection-by-slug.md): Fetches a single collection by its `slug`.
* [Get a collection](https://developers.telnyx.com/api-reference/ai-collections/get-a-collection.md): Fetches a single collection by its `uuid`.
* [Update a collection](https://developers.telnyx.com/api-reference/ai-collections/update-a-collection.md): Updates a collection's metadata (`name` and/or `description`). Sources and settings are managed through their own sub-resources.
* [Delete a collection](https://developers.telnyx.com/api-reference/ai-collections/delete-a-collection.md): Soft-deletes a collection. Its `slug` is freed and may be reused by a new collection.
* [List collection sources](https://developers.telnyx.com/api-reference/ai-collections/list-collection-sources.md): Returns the sources attached to a collection.
* [Add a collection source](https://developers.telnyx.com/api-reference/ai-collections/add-a-collection-source.md): Attaches a new source to a collection.
* [Replace collection sources](https://developers.telnyx.com/api-reference/ai-collections/replace-collection-sources.md): Replaces the collection's entire source set. The response `meta` reports which sources were added, retained, and removed.
* [Remove a collection source](https://developers.telnyx.com/api-reference/ai-collections/remove-a-collection-source.md): Removes a single source from a collection.
* [Get collection settings](https://developers.telnyx.com/api-reference/ai-collections/get-collection-settings.md): Returns the retrieval settings for a collection.
* [Replace collection settings](https://developers.telnyx.com/api-reference/ai-collections/replace-collection-settings.md): Replaces the collection's retrieval settings.
* [Update collection settings](https://developers.telnyx.com/api-reference/ai-collections/update-collection-settings.md): Partially updates the collection's retrieval settings.
* [Search collection documents](https://developers.telnyx.com/api-reference/ai-collections/search-collection-documents.md): Runs search over the documents in a collection, ranked by relevance to `query`. The collection's `retrieval_type` setting selects the strategy: `vector` (seman…
