---
title: "Manage document collections for retrieval"
description: "Create and manage document collections, add text documents to one, and attach it to a folder or agent so its content gets pulled into chats and calls."
---

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

# Manage document collections for retrieval


import EndpointIndex from "@/components/api/EndpointIndex.astro";

The Speak AI API exposes 14 knowledge base endpoints under the base URL `https://api.speakai.co/v1`. Every request needs the `x-speakai-key` and `x-access-token` headers described in [Authentication](/api/authentication/).

## What can you do with the knowledge base endpoints?

Speak AI groups these 14 endpoints under the knowledge base resource. Each entry below links to the full reference for that endpoint further down this page.

### Collections

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | [`/knowledge-bases`](#get-knowledge-bases) | List Knowledge Base Collections |
| `POST` | [`/knowledge-bases`](#post-knowledge-bases) | Create Knowledge Base Collection |
| `GET` | [`/knowledge-bases/{kbId}`](#get-knowledge-bases-kb-id) | Get Knowledge Base Collection |
| `PATCH` | [`/knowledge-bases/{kbId}`](#patch-knowledge-bases-kb-id) | Update Knowledge Base Collection |
| `DELETE` | [`/knowledge-bases/{kbId}`](#delete-knowledge-bases-kb-id) | Delete Knowledge Base Collection |

### Documents

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | [`/knowledge-bases/{kbId}/documents`](#get-knowledge-bases-kb-id-documents) | List Knowledge Base Documents |
| `PATCH` | [`/knowledge-bases/{kbId}/documents/{docId}`](#patch-knowledge-bases-kb-id-documents-doc-id) | Update Knowledge Base Document |
| `DELETE` | [`/knowledge-bases/{kbId}/documents/{docId}`](#delete-knowledge-bases-kb-id-documents-doc-id) | Delete Knowledge Base Document |
| `GET` | [`/knowledge-bases/{kbId}/documents/{docId}/text`](#get-knowledge-bases-kb-id-documents-doc-id-text) | Get Knowledge Base Document Text |
| `POST` | [`/knowledge-bases/{kbId}/documents/manual`](#post-knowledge-bases-kb-id-documents-manual) | Add Knowledge Base Text Document |

### Owner mapping

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | [`/knowledge-bases/{kbId}/owners`](#get-knowledge-bases-kb-id-owners) | List Knowledge Base Collection Owners |
| `POST` | [`/knowledge-bases/{kbId}/map`](#post-knowledge-bases-kb-id-map) | Map Knowledge Base Collection |
| `DELETE` | [`/knowledge-bases/{kbId}/map`](#delete-knowledge-bases-kb-id-map) | Unmap Knowledge Base Collection |
| `GET` | [`/knowledge-bases/owners/{ownerType}/{ownerId}/collections`](#get-knowledge-bases-owners-owner-type-owner-id-collections) | List Collections for an Owner |

## Collections

<h2 id="get-knowledge-bases">List Knowledge Base Collections</h2>

#### List Collections

Lists every collection in your company, newest first. Each item is enriched with documentCount and a rolled-up status the single-collection Get endpoint does not return.

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/knowledge-bases' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-knowledge-bases" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object[] |  |

<details>
<summary>`data` -- 8 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `knowledgeBaseId` | string | Server-generated. Immutable. The identifier used everywhere for this collection. |
| `name` | string | Up to 200 characters. |
| `description` | string | Up to 1000 characters. |
| `documents` | object |  |
| `documents.embeddingStatus` | string | One of: `pending`, `processing`, `completed`, `failed` . |
| `documents.lastIndexedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |
| `documentCount` | number | Only present in the list response, not on a single collection fetched by id. |
| `status` | string | Rolled up from this collection's documents. Only present in the list response. Distinct from documents.embeddingStatus, which is a stored field on the collection itself. One of: `empty`, `processing`, `ready`, `failed` . |

</details>

</div>

</ResponsePanel>

</div>

<h2 id="post-knowledge-bases">Create Knowledge Base Collection</h2>

#### Create Collection

Requires the OWNER or ADMIN role. Creates an empty document collection. Add documents to it with the manual-document endpoint, then attach it to a folder or agent with the map endpoint so something actually uses it.

### Request body

Fields marked **required** are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.

| Field | Type | Description |
| --- | --- | --- |
| `name` | string, **required** | Up to 200 characters. Required. |
| `description` | string | Up to 1000 characters. Optional. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/knowledge-bases' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

</CodePanel>

<ResponsePanel id="post-knowledge-bases" statuses={[{"code":"201","description":"Created"},{"code":"400","description":"Bad Request"},{"code":"403","description":"Forbidden"}]}>

<div slot="status-201">

**`201` Created**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |

<details>
<summary>`data` -- 6 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `knowledgeBaseId` | string | Server-generated. Immutable. The identifier used everywhere for this collection. |
| `name` | string | Up to 200 characters. |
| `description` | string | Up to 1000 characters. |
| `documents` | object |  |
| `documents.embeddingStatus` | string | One of: `pending`, `processing`, `completed`, `failed` . |
| `documents.lastIndexedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

</div>

<div slot="status-400">

**`400` Bad Request**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string |  |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

</ResponsePanel>

</div>

<h2 id="get-knowledge-bases-kb-id">Get Knowledge Base Collection</h2>

#### Get Collection

Fetches one collection by id, company-scoped. Does not include documentCount or status -- those are only on the list response.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/knowledge-bases/KB_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-knowledge-bases-kb-id" statuses={[{"code":"200","description":"OK"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |

<details>
<summary>`data` -- 6 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `knowledgeBaseId` | string | Server-generated. Immutable. The identifier used everywhere for this collection. |
| `name` | string | Up to 200 characters. |
| `description` | string | Up to 1000 characters. |
| `documents` | object |  |
| `documents.embeddingStatus` | string | One of: `pending`, `processing`, `completed`, `failed` . |
| `documents.lastIndexedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Knowledge base not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="patch-knowledge-bases-kb-id">Update Knowledge Base Collection</h2>

#### Update Collection

Requires the OWNER or ADMIN role. Partial update: send only the fields to change. At least one of name or description is required.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |

### Request body

Fields marked **required** are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.

| Field | Type | Description |
| --- | --- | --- |
| `name` | string | Up to 200 characters. |
| `description` | string | Up to 1000 characters. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X PATCH 'https://api.speakai.co/v1/knowledge-bases/KB_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

</CodePanel>

<ResponsePanel id="patch-knowledge-bases-kb-id" statuses={[{"code":"200","description":"OK"},{"code":"400","description":"Bad Request"},{"code":"403","description":"Forbidden"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |

<details>
<summary>`data` -- 6 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `knowledgeBaseId` | string | Server-generated. Immutable. The identifier used everywhere for this collection. |
| `name` | string | Up to 200 characters. |
| `description` | string | Up to 1000 characters. |
| `documents` | object |  |
| `documents.embeddingStatus` | string | One of: `pending`, `processing`, `completed`, `failed` . |
| `documents.lastIndexedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

</div>

<div slot="status-400">

**`400` Bad Request**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string |  |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Knowledge base not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="delete-knowledge-bases-kb-id">Delete Knowledge Base Collection</h2>

#### Delete Collection

Requires the OWNER or ADMIN role. Deletes the collection, every document in it, their embeddings, and every mapping row pointing at it. An automation step that still names this collection is not touched -- it starts failing to retrieve rather than being silently unlinked.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X DELETE 'https://api.speakai.co/v1/knowledge-bases/KB_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="delete-knowledge-bases-kb-id" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Forbidden"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |
| `data.knowledgeBaseId` | string |  |
| `data.deleted` | boolean | One of: `true` . |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Knowledge base not found` . |

</div>

</ResponsePanel>

</div>

## Documents

<h2 id="get-knowledge-bases-kb-id-documents">List Knowledge Base Documents</h2>

#### List Documents

Lists every document in the collection, newest first. Each item's full text is not included -- fetch it separately from Get Document Text.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/knowledge-bases/KB_ID/documents' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-knowledge-bases-kb-id-documents" statuses={[{"code":"200","description":"OK"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object[] |  |

<details>
<summary>`data` -- 14 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `documentId` | string | Server-generated. Immutable. |
| `knowledgeBaseId` | string |  |
| `source` | string | This endpoint set only creates manual documents; upload and website documents come from endpoints not covered here. One of: `upload`, `website`, `manual` . |
| `title` | string |  |
| `description` | string |  |
| `fileName` | string | Set only for an uploaded file. |
| `mimeType` | string |  |
| `sizeBytes` | number |  |
| `sourceUrl` | string | Set only for a website document. |
| `pageUrl` | string | Set only for a website document. |
| `status` | string | One of: `uploaded`, `parsing`, `parsed`, `embedding`, `ready`, `failed` . |
| `error` | string |  |
| `parse` | object |  |
| `parse.engine` | string |  |
| `parse.pages` | number |  |
| `parse.costUsd` | number |  |
| `parse.parsedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |

</details>

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Knowledge base not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="patch-knowledge-bases-kb-id-documents-doc-id">Update Knowledge Base Document</h2>

#### Update Document

Requires the OWNER or ADMIN role. Renames the document's title and/or description -- the only fields this endpoint can change, at any status. A title change also propagates to that document's stored chunk metadata so retrieval citations pick it up immediately.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |
| `docId` | path | string | Yes | The document's documentId. |

### Request body

Fields marked **required** are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.

| Field | Type | Description |
| --- | --- | --- |
| `title` | string | Cannot be sent as an empty string. |
| `description` | string |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X PATCH 'https://api.speakai.co/v1/knowledge-bases/KB_ID/documents/DOC_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

</CodePanel>

<ResponsePanel id="patch-knowledge-bases-kb-id-documents-doc-id" statuses={[{"code":"200","description":"OK"},{"code":"400","description":"Bad Request"},{"code":"403","description":"Forbidden"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |

<details>
<summary>`data` -- 14 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `documentId` | string | Server-generated. Immutable. |
| `knowledgeBaseId` | string |  |
| `source` | string | This endpoint set only creates manual documents; upload and website documents come from endpoints not covered here. One of: `upload`, `website`, `manual` . |
| `title` | string |  |
| `description` | string |  |
| `fileName` | string | Set only for an uploaded file. |
| `mimeType` | string |  |
| `sizeBytes` | number |  |
| `sourceUrl` | string | Set only for a website document. |
| `pageUrl` | string | Set only for a website document. |
| `status` | string | One of: `uploaded`, `parsing`, `parsed`, `embedding`, `ready`, `failed` . |
| `error` | string |  |
| `parse` | object |  |
| `parse.engine` | string |  |
| `parse.pages` | number |  |
| `parse.costUsd` | number |  |
| `parse.parsedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |

</details>

</div>

<div slot="status-400">

**`400` Bad Request**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string |  |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Document not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="delete-knowledge-bases-kb-id-documents-doc-id">Delete Knowledge Base Document</h2>

#### Delete Document

Requires the OWNER or ADMIN role. Deletes the document and its embeddings. Looked up by documentId and your company alone -- the kbId in the path is not cross-checked against the document's own collection, so this succeeds even if docId actually belongs to a different one of your collections.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |
| `docId` | path | string | Yes | The document's documentId. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X DELETE 'https://api.speakai.co/v1/knowledge-bases/KB_ID/documents/DOC_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="delete-knowledge-bases-kb-id-documents-doc-id" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Forbidden"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |
| `data.documentId` | string |  |
| `data.deleted` | boolean | One of: `true` . |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Document not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="get-knowledge-bases-kb-id-documents-doc-id-text">Get Knowledge Base Document Text</h2>

#### Get Document Text

Fetches the extracted text of one document, company-scoped. A document that has not finished parsing yet is not an error: available is false, text is an empty string, and status shows the document's current state.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |
| `docId` | path | string | Yes | The document's documentId. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/knowledge-bases/KB_ID/documents/DOC_ID/text' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-knowledge-bases-kb-id-documents-doc-id-text" statuses={[{"code":"200","description":"OK"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |
| `data.documentId` | string |  |
| `data.status` | string | One of: `uploaded`, `parsing`, `parsed`, `embedding`, `ready`, `failed` . |
| `data.available` | boolean | True once text.length > 0. |
| `data.text` | string |  |
| `data.length` | number | Character count, not bytes. |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Document not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="post-knowledge-bases-kb-id-documents-manual">Add Knowledge Base Text Document</h2>

#### Add a Text Document

Requires the OWNER or ADMIN role. Adds a document with text you supply directly -- the only way this endpoint set creates a document (uploading a file or crawling a website use endpoints not covered here). Kicks off embedding immediately; status starts at uploaded and moves toward ready on its own.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |

### Request body

Fields marked **required** are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.

| Field | Type | Description |
| --- | --- | --- |
| `title` | string, **required** | Up to 200 characters. Required. |
| `text` | string, **required** | Required, non-empty. Size-capped server-side; an oversized submission is a 400 asking you to split it into smaller entries. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/knowledge-bases/KB_ID/documents/manual' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

</CodePanel>

<ResponsePanel id="post-knowledge-bases-kb-id-documents-manual" statuses={[{"code":"201","description":"Created"},{"code":"400","description":"Bad Request"},{"code":"403","description":"Forbidden"},{"code":"404","description":"Not Found"}]}>

<div slot="status-201">

**`201` Created**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |

<details>
<summary>`data` -- 14 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `documentId` | string | Server-generated. Immutable. |
| `knowledgeBaseId` | string |  |
| `source` | string | This endpoint set only creates manual documents; upload and website documents come from endpoints not covered here. One of: `upload`, `website`, `manual` . |
| `title` | string |  |
| `description` | string |  |
| `fileName` | string | Set only for an uploaded file. |
| `mimeType` | string |  |
| `sizeBytes` | number |  |
| `sourceUrl` | string | Set only for a website document. |
| `pageUrl` | string | Set only for a website document. |
| `status` | string | One of: `uploaded`, `parsing`, `parsed`, `embedding`, `ready`, `failed` . |
| `error` | string |  |
| `parse` | object |  |
| `parse.engine` | string |  |
| `parse.pages` | number |  |
| `parse.costUsd` | number |  |
| `parse.parsedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |

</details>

</div>

<div slot="status-400">

**`400` Bad Request**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string |  |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Knowledge base not found` . |

</div>

</ResponsePanel>

</div>

## Owner mapping

<h2 id="get-knowledge-bases-kb-id-owners">List Knowledge Base Collection Owners</h2>

#### List Collection Owners

Everything this collection is attached to: folder and agent mappings from the map endpoint, plus every automation whose AI step names this collection directly (automations are never in the mapping table -- their link is read live from the automation's own steps, so it can't go stale).

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/knowledge-bases/KB_ID/owners' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-knowledge-bases-kb-id-owners" statuses={[{"code":"200","description":"OK"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object[] |  |
| `data[].knowledgeBaseId` | string |  |
| `data[].ownerType` | string | One of: `folder`, `agent`, `automation` . |
| `data[].ownerId` | string |  |
| `data[].ownerName` | string | Only present when ownerType is automation -- the automation's name, looked up live from its own record, not stored on a mapping row. |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Knowledge base not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="post-knowledge-bases-kb-id-map">Map Knowledge Base Collection</h2>

#### Attach a Collection

Requires the OWNER or ADMIN role. Attaches this collection to a folder or agent, so retrieval actually uses it -- a collection with no mapping is created but inert. Idempotent: mapping the same (collection, owner) pair again returns the existing row rather than erroring. ownerType cannot be automation here -- an automation's collection is set on its own AI step, not through this endpoint; see Get Collection Owners for how that link is surfaced instead.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |

### Request body

Fields marked **required** are the ones the server rejects the request without. Anything conditional, where a field becomes required only alongside another, is described under Request rules above rather than marked here.

| Field | Type | Description |
| --- | --- | --- |
| `ownerType` | string, **required** | One of: `folder`, `agent` . |
| `ownerId` | string, **required** |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/knowledge-bases/KB_ID/map' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

</CodePanel>

<ResponsePanel id="post-knowledge-bases-kb-id-map" statuses={[{"code":"200","description":"OK"},{"code":"400","description":"Bad Request"},{"code":"403","description":"Forbidden"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |
| `data.knowledgeBaseId` | string |  |
| `data.ownerType` | string | Never automation here: an automation's collection lives on its own AI step, not a mapping row -- see GET .../owners for how an automation link is surfaced instead. One of: `folder`, `agent` . |
| `data.ownerId` | string |  |
| `data.createdAt` | string (date-time) |  |

</div>

<div slot="status-400">

**`400` Bad Request**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string |  |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Knowledge base not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="delete-knowledge-bases-kb-id-map">Unmap Knowledge Base Collection</h2>

#### Detach a Collection

Requires the OWNER or ADMIN role. Removes one mapping row. ownerType and ownerId are sent as query parameters on this DELETE, not a request body.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `kbId` | path | string | Yes | The collection's knowledgeBaseId. |
| `ownerType` | query | string | Yes |  |
| `ownerId` | query | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X DELETE 'https://api.speakai.co/v1/knowledge-bases/KB_ID/map' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="delete-knowledge-bases-kb-id-map" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Forbidden"},{"code":"404","description":"Not Found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |
| `data.knowledgeBaseId` | string |  |
| `data.ownerType` | string |  |
| `data.ownerId` | string |  |
| `data.unmapped` | boolean | One of: `true` . |

</div>

<div slot="status-403">

**`403` Forbidden**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `You do not have permission to manage knowledge bases` . |

</div>

<div slot="status-404">

**`404` Not Found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `message` | string | One of: `Mapping not found` . |

</div>

</ResponsePanel>

</div>

<h2 id="get-knowledge-bases-owners-owner-type-owner-id-collections">List Collections for an Owner</h2>

#### List an Owner's Collections

Reverse lookup: every collection mapped to a given folder or agent. Only covers real mapping rows, so an automation's collection (which is never mapped, only referenced from its own AI step) will not appear here even though it shows up in that collection's own Get Collection Owners response.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `ownerType` | path | string | Yes |  |
| `ownerId` | path | string | Yes | The folder or agent id. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X GET 'https://api.speakai.co/v1/knowledge-bases/owners/OWNER_TYPE/OWNER_ID/collections' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="get-knowledge-bases-owners-owner-type-owner-id-collections" statuses={[{"code":"200","description":"OK"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object[] |  |

<details>
<summary>`data` -- 6 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `knowledgeBaseId` | string | Server-generated. Immutable. The identifier used everywhere for this collection. |
| `name` | string | Up to 200 characters. |
| `description` | string | Up to 1000 characters. |
| `documents` | object |  |
| `documents.embeddingStatus` | string | One of: `pending`, `processing`, `completed`, `failed` . |
| `documents.lastIndexedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

</div>

</ResponsePanel>

</div>

## Related pages

- [API reference](/api/) for the base URL, authentication, and the error format.
- [Authenticate with the Speak AI API using access tokens](/api/authentication/)
- [Upload audio and video to Speak AI and read insights](/api/media/)
- [Create and update live transcription sessions](/api/live-transcription/)
- [Analyze text notes with the Speak AI text endpoints](/api/text/)

Get an API key on the [Speak AI developer page](https://app.speakai.co/developers?utm_source=docs&utm_medium=referral&utm_campaign=api-reference&utm_content=api-knowledge-base).

Source: https://docs.speakai.co/api/knowledge-base/index.mdx
