---
title: "Close a voice agent's knowledge gaps"
description: "Self-improvement surfaced from real calls: knowledge base gaps, FAQ suggestions, instruction gaps in the agent's prompt, and its knowledge base links."
---

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

# Close a voice agent's knowledge gaps


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

The Speak AI API exposes 16 intelligence 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 intelligence endpoints?

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

### Agent Resources

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | [`/voice/agent-resources`](#get-voice-agent-resources) | List Agent Resources |
| `POST` | [`/voice/agent-resources`](#post-voice-agent-resources) | Create Agent Resource |
| `PUT` | [`/voice/agent-resources/{resourceId}`](#put-voice-agent-resources-resource-id) | Update Agent Resource |
| `DELETE` | [`/voice/agent-resources/{resourceId}`](#delete-voice-agent-resources-resource-id) | Delete Agent Resource |
| `POST` | [`/voice/agent-resources/bulk`](#post-voice-agent-resources-bulk) | Bulk Create Agent Resources |

### FAQs

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | [`/voice/knowledge-base/{agentId}/faqs`](#get-voice-knowledge-base-agent-id-faqs) | List FAQ Suggestions |
| `PUT` | [`/voice/knowledge-base/{agentId}/faqs/{suggestionId}`](#put-voice-knowledge-base-agent-id-faqs-suggestion-id) | Update FAQ Suggestion |
| `DELETE` | [`/voice/knowledge-base/{agentId}/faqs/{suggestionId}`](#delete-voice-knowledge-base-agent-id-faqs-suggestion-id) | Dismiss FAQ Suggestion |
| `POST` | [`/voice/knowledge-base/{agentId}/faqs/{suggestionId}/add`](#post-voice-knowledge-base-agent-id-faqs-suggestion-id-add) | Add FAQ To KB |
| `POST` | [`/voice/knowledge-base/{agentId}/faqs/generate`](#post-voice-knowledge-base-agent-id-faqs-generate) | Generate FAQ Suggestions |

### Knowledge Base Gaps

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | [`/voice/knowledge-base/{agentId}/gaps`](#get-voice-knowledge-base-agent-id-gaps) | List KB Gaps |
| `DELETE` | [`/voice/knowledge-base/{agentId}/gaps/{gapId}`](#delete-voice-knowledge-base-agent-id-gaps-gap-id) | Dismiss Gap |
| `POST` | [`/voice/knowledge-base/{agentId}/gaps/{gapId}/add`](#post-voice-knowledge-base-agent-id-gaps-gap-id-add) | Add Gap To KB |
| `POST` | [`/voice/knowledge-base/{agentId}/gaps/analyze`](#post-voice-knowledge-base-agent-id-gaps-analyze) | Analyze KB Gaps |

### Instruction Gaps

| Method | Path | What it does |
| --- | --- | --- |
| `POST` | [`/voice/agents/{agentId}/generation/gaps/analyze`](#post-voice-agents-agent-id-generation-gaps-analyze) | Analyze Instruction Gaps |
| `POST` | [`/voice/agents/{agentId}/generation/gaps/apply`](#post-voice-agents-agent-id-generation-gaps-apply) | Apply Instruction Gap |

## Agent Resources

<h2 id="get-voice-agent-resources">List Agent Resources</h2>

#### List Agent Resources

Lists the knowledge documents/links an agent searches during calls -- separate from the KB Gaps and FAQ Suggestions above, which are the self-improvement layer that surfaces what an agent is missing, not the content itself. Paginated; optionally scoped to one agentId, and searchable by title/description.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | query | string | No | Scope to one agent's resources. Omit to list across all your agents. |
| `page` | query | integer | No | Defaults to 1. |
| `limit` | query | integer | No | Defaults to 10, max 100. |
| `search` | query | string | No | Case-insensitive match against title or description. |

<div slot="code">

<CodePanel label="Example request">

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

</CodePanel>

<ResponsePanel id="get-voice-agent-resources" 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 |  |
| `data.resources` | object[] |  |
| `data.total` | integer |  |
| `data.page` | integer |  |
| `data.limit` | integer |  |

<details>
<summary>`data.resources` -- 15 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `_id` | string | MongoDB document id, included because every document has one; use resourceId to identify it. |
| `resourceId` | string | Server-generated UUID. Immutable -- sent in the body on create or update is silently dropped. |
| `agentId` | string | Required on create. Immutable after create -- sent on update is silently dropped. |
| `companyId` | string | Stamped from the caller's authenticated company. Sent in the body is silently dropped. |
| `userId` | string | Id of the user who created this resource. Sent in the body is silently dropped. |
| `url` | string (uri) | Required on create. |
| `title` | string | Required on create. Max 200 characters. |
| `description` | string | Required on create. Max 1000 characters. |
| `action` | string | Required on create. One of: `link`, `presentation` . |
| `contentType` | string | One of: `video`, `pdf`, `image` . |
| `status` | string | Defaults to pending. Advances as the resource's content is fetched and embedded for the agent to search during calls. Not settable directly. One of: `pending`, `uploading`, `processing`, `completed`, `failed` . |
| `isDeleted` | boolean | Delete is a soft delete. Not settable directly. |
| `deletedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"resources": [
  {
    "resourceId": "res-2a9f",
    "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "url": "https://docs.example.com/pricing",
    "title": "Pricing page",
    "description": "Current plan pricing and feature comparison",
    "action": "link",
    "status": "completed",
    "isDeleted": false,
    "createdAt": "2026-08-01T12:00:00.000Z",
    "updatedAt": "2026-08-01T12:00:00.000Z"
  }
],
"total": 1,
"page": 1,
"limit": 10
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-voice-agent-resources">Create Agent Resource</h2>

#### Create Agent Resource

Requires the OWNER or ADMIN role. Adds one document/link to an agent's knowledge base; the server fetches and embeds the content in the background (status moves from pending to completed).

### 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 |
| --- | --- | --- |
| `agentId` | string, **required** | Required. |
| `url` | string (uri), **required** | Required. |
| `title` | string, **required** | Required. Max 200 characters. |
| `description` | string, **required** | Required. Max 1000 characters. |
| `action` | string, **required** | Required. One of: `link`, `presentation` . |
| `contentType` | string | One of: `video`, `pdf`, `image` . |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/agent-resources' \
  -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-voice-agent-resources" statuses={[{"code":"201","description":"Created"},{"code":"400","description":"Validation failed"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Agent not found"}]}>

<div slot="status-201">

**`201` Created**

Response body, `application/json`.

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

<details>
<summary>`data.resource` -- 15 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `_id` | string | MongoDB document id, included because every document has one; use resourceId to identify it. |
| `resourceId` | string | Server-generated UUID. Immutable -- sent in the body on create or update is silently dropped. |
| `agentId` | string | Required on create. Immutable after create -- sent on update is silently dropped. |
| `companyId` | string | Stamped from the caller's authenticated company. Sent in the body is silently dropped. |
| `userId` | string | Id of the user who created this resource. Sent in the body is silently dropped. |
| `url` | string (uri) | Required on create. |
| `title` | string | Required on create. Max 200 characters. |
| `description` | string | Required on create. Max 1000 characters. |
| `action` | string | Required on create. One of: `link`, `presentation` . |
| `contentType` | string | One of: `video`, `pdf`, `image` . |
| `status` | string | Defaults to pending. Advances as the resource's content is fetched and embedded for the agent to search during calls. Not settable directly. One of: `pending`, `uploading`, `processing`, `completed`, `failed` . |
| `isDeleted` | boolean | Delete is a soft delete. Not settable directly. |
| `deletedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"resource": {
  "resourceId": "res-2a9f",
  "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "url": "https://docs.example.com/pricing",
  "title": "Pricing page",
  "description": "Current plan pricing and feature comparison",
  "action": "link",
  "status": "completed",
  "isDeleted": false,
  "createdAt": "2026-08-01T12:00:00.000Z",
  "updatedAt": "2026-08-01T12:00:00.000Z"
}
  }
}
```

</div>

<div slot="status-400">

**`400` Validation failed**

Response body, `application/json`.

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

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agent resources"
}
```

</div>

<div slot="status-404">

**`404` Agent not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Agent not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

<h2 id="put-voice-agent-resources-resource-id">Update Agent Resource</h2>

#### Update Agent Resource

Requires the OWNER or ADMIN role. Partial update -- send at least one field. agentId cannot be changed. Changing url, title, or description re-triggers embedding.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `resourceId` | path | string | Yes |  |

### 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 |
| --- | --- | --- |
| `url` | string (uri) | Required. |
| `title` | string | Required. Max 200 characters. |
| `description` | string | Required. Max 1000 characters. |
| `action` | string | Required. One of: `link`, `presentation` . |
| `contentType` | string | One of: `video`, `pdf`, `image` . |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X PUT 'https://api.speakai.co/v1/voice/agent-resources/RESOURCE_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="put-voice-agent-resources-resource-id" statuses={[{"code":"200","description":"OK"},{"code":"400","description":"Validation failed"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Resource not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

<details>
<summary>`data.resource` -- 15 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `_id` | string | MongoDB document id, included because every document has one; use resourceId to identify it. |
| `resourceId` | string | Server-generated UUID. Immutable -- sent in the body on create or update is silently dropped. |
| `agentId` | string | Required on create. Immutable after create -- sent on update is silently dropped. |
| `companyId` | string | Stamped from the caller's authenticated company. Sent in the body is silently dropped. |
| `userId` | string | Id of the user who created this resource. Sent in the body is silently dropped. |
| `url` | string (uri) | Required on create. |
| `title` | string | Required on create. Max 200 characters. |
| `description` | string | Required on create. Max 1000 characters. |
| `action` | string | Required on create. One of: `link`, `presentation` . |
| `contentType` | string | One of: `video`, `pdf`, `image` . |
| `status` | string | Defaults to pending. Advances as the resource's content is fetched and embedded for the agent to search during calls. Not settable directly. One of: `pending`, `uploading`, `processing`, `completed`, `failed` . |
| `isDeleted` | boolean | Delete is a soft delete. Not settable directly. |
| `deletedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"resource": {
  "resourceId": "res-2a9f",
  "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "url": "https://docs.example.com/pricing",
  "title": "Pricing page",
  "description": "Current plan pricing and feature comparison",
  "action": "link",
  "status": "completed",
  "isDeleted": false,
  "createdAt": "2026-08-01T12:00:00.000Z",
  "updatedAt": "2026-08-01T12:00:00.000Z"
}
  }
}
```

</div>

<div slot="status-400">

**`400` Validation failed**

Response body, `application/json`.

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

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agent resources"
}
```

</div>

<div slot="status-404">

**`404` Resource not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Resource not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

<h2 id="delete-voice-agent-resources-resource-id">Delete Agent Resource</h2>

#### Delete Agent Resource

Requires the OWNER or ADMIN role. Soft-deletes the resource (isDeleted set true) -- it stops appearing in lists and the agent stops searching it, but the document is not physically removed.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `resourceId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X DELETE 'https://api.speakai.co/v1/voice/agent-resources/RESOURCE_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="delete-voice-agent-resources-resource-id" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Resource not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "Resource deleted successfully"
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agent resources"
}
```

</div>

<div slot="status-404">

**`404` Resource not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Resource not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-voice-agent-resources-bulk">Bulk Create Agent Resources</h2>

#### Bulk Create Agent Resources

Requires the OWNER or ADMIN role. Adds up to 100 documents/links in one call; each is fetched and embedded independently in the background.

### 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 |
| --- | --- | --- |
| `agentId` | string, **required** | Required. |
| `resources` | object[], **required** | Required. 1 to 100 entries, each shaped like the Create Agent Resource request body minus agentId. |

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

| Field | Type | Description |
| --- | --- | --- |
| `agentId` | string | Required. |
| `url` | string (uri) | Required. |
| `title` | string | Required. Max 200 characters. |
| `description` | string | Required. Max 1000 characters. |
| `action` | string | Required. One of: `link`, `presentation` . |
| `contentType` | string | One of: `video`, `pdf`, `image` . |

</details>

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/agent-resources/bulk' \
  -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-voice-agent-resources-bulk" statuses={[{"code":"201","description":"Created"},{"code":"400","description":"Validation failed"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Agent not found"}]}>

<div slot="status-201">

**`201` Created**

Response body, `application/json`.

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

<details>
<summary>`data.resources` -- 15 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `_id` | string | MongoDB document id, included because every document has one; use resourceId to identify it. |
| `resourceId` | string | Server-generated UUID. Immutable -- sent in the body on create or update is silently dropped. |
| `agentId` | string | Required on create. Immutable after create -- sent on update is silently dropped. |
| `companyId` | string | Stamped from the caller's authenticated company. Sent in the body is silently dropped. |
| `userId` | string | Id of the user who created this resource. Sent in the body is silently dropped. |
| `url` | string (uri) | Required on create. |
| `title` | string | Required on create. Max 200 characters. |
| `description` | string | Required on create. Max 1000 characters. |
| `action` | string | Required on create. One of: `link`, `presentation` . |
| `contentType` | string | One of: `video`, `pdf`, `image` . |
| `status` | string | Defaults to pending. Advances as the resource's content is fetched and embedded for the agent to search during calls. Not settable directly. One of: `pending`, `uploading`, `processing`, `completed`, `failed` . |
| `isDeleted` | boolean | Delete is a soft delete. Not settable directly. |
| `deletedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"resources": [
  {
    "resourceId": "res-2a9f",
    "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "url": "https://docs.example.com/pricing",
    "title": "Pricing page",
    "description": "Current plan pricing and feature comparison",
    "action": "link",
    "status": "completed",
    "isDeleted": false,
    "createdAt": "2026-08-01T12:00:00.000Z",
    "updatedAt": "2026-08-01T12:00:00.000Z"
  }
],
"total": 1
  }
}
```

</div>

<div slot="status-400">

**`400` Validation failed**

Response body, `application/json`.

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

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agent resources"
}
```

</div>

<div slot="status-404">

**`404` Agent not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Agent not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

## FAQs

<h2 id="get-voice-knowledge-base-agent-id-faqs">List FAQ Suggestions</h2>

#### List FAQ Suggestions

Lists this agent's pending FAQ suggestions -- questions multiple callers asked in similar form, clustered and drafted into a reusable question/answer pair. Up to the 20 largest clusters, largest first.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

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

</CodePanel>

<ResponsePanel id="get-voice-knowledge-base-agent-id-faqs" 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 |  |
| `data.faqs` | object[] |  |

<details>
<summary>`data.faqs` -- 11 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `_id` | string | MongoDB document id, included because every document has one; use suggestionId to identify it. |
| `suggestionId` | string | Server-generated. Immutable. Used as the suggestionId path parameter on every FAQ endpoint. |
| `agentId` | string |  |
| `question` | string |  |
| `answer` | string |  |
| `sourceConversationIds` | string[] | The calls this FAQ was clustered from. See Conversations. |
| `clusterSize` | integer | How many similar caller questions were grouped into this one suggestion. |
| `status` | string | One of: `pending`, `added`, `dismissed` . |
| `resolvedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"faqs": [
  {
    "suggestionId": "sugg-7c2e",
    "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "question": "What are your business hours?",
    "answer": "We're open Monday to Friday, 9am to 5pm.",
    "sourceConversationIds": [
      "c9d8e7f6-a5b4-3210-9876-543210fedcba"
    ],
    "clusterSize": 4,
    "status": "pending",
    "resolvedAt": null,
    "createdAt": "2026-08-01T12:00:00.000Z",
    "updatedAt": "2026-08-01T12:00:00.000Z"
  }
]
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="put-voice-knowledge-base-agent-id-faqs-suggestion-id">Update FAQ Suggestion</h2>

#### Update FAQ Suggestion

Requires the OWNER or ADMIN role. Edits a still-pending suggestion's question and/or answer before adding it. Fails with 400 if the suggestion was already added or dismissed.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |
| `suggestionId` | path | string | Yes | The FAQ suggestion's suggestionId. |

### 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 |
| --- | --- | --- |
| `question` | string | Overrides the suggested question. Optional. |
| `answer` | string | Overrides the suggested answer. Optional. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X PUT 'https://api.speakai.co/v1/voice/knowledge-base/AGENT_ID/faqs/SUGGESTION_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="put-voice-knowledge-base-agent-id-faqs-suggestion-id" statuses={[{"code":"200","description":"OK"},{"code":"400","description":"Cannot edit a resolved FAQ"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"FAQ not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "FAQ updated"
}
```

</div>

<div slot="status-400">

**`400` Cannot edit a resolved FAQ**

Response body, `application/json`.

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

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` FAQ not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "FAQ not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

<h2 id="delete-voice-knowledge-base-agent-id-faqs-suggestion-id">Dismiss FAQ Suggestion</h2>

#### Dismiss FAQ Suggestion

Requires the OWNER or ADMIN role. Marks the suggestion dismissed without writing anything to the knowledge base.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |
| `suggestionId` | path | string | Yes | The FAQ suggestion's suggestionId. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X DELETE 'https://api.speakai.co/v1/voice/knowledge-base/AGENT_ID/faqs/SUGGESTION_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="delete-voice-knowledge-base-agent-id-faqs-suggestion-id" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"FAQ not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "FAQ dismissed"
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` FAQ not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "FAQ not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-voice-knowledge-base-agent-id-faqs-suggestion-id-add">Add FAQ To KB</h2>

#### Add FAQ To Knowledge Base

Requires the OWNER or ADMIN role. Writes the question/answer (or your override) into the agent's knowledge base as a new document, and marks the suggestion added. Fails with 409 if the suggestion was already added or dismissed, or if the agent has no knowledge base collection to write into.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |
| `suggestionId` | path | string | Yes | The FAQ suggestion's suggestionId. |

### 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 |
| --- | --- | --- |
| `question` | string | Overrides the suggested question. Optional. |
| `answer` | string | Overrides the suggested answer. Optional. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/knowledge-base/AGENT_ID/faqs/SUGGESTION_ID/add' \
  -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-voice-knowledge-base-agent-id-faqs-suggestion-id-add" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"FAQ not found"},{"code":"409","description":"Conflict"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "Added to knowledge base"
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` FAQ not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "FAQ not found",
  "hints": []
}
```

</div>

<div slot="status-409">

**`409` Conflict**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "FAQ already resolved"
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-voice-knowledge-base-agent-id-faqs-generate">Generate FAQ Suggestions</h2>

#### Generate FAQ Suggestions

Requires the OWNER or ADMIN role. Triggers FAQ clustering over this agent's recent calls in the background and returns immediately -- new suggestions appear in the list once generation finishes, which is not synchronous with this response.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/knowledge-base/AGENT_ID/faqs/generate' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="post-voice-knowledge-base-agent-id-faqs-generate" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Agent not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "FAQ generation started"
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` Agent not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Agent not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

## Knowledge Base Gaps

<h2 id="get-voice-knowledge-base-agent-id-gaps">List KB Gaps</h2>

#### List Knowledge Base Gaps

Lists this agent's pending KB gaps -- questions callers asked that the agent answered with low confidence or an explicit "I don't know," surfaced automatically after calls. Up to the 50 most recent pending gaps, newest first.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

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

</CodePanel>

<ResponsePanel id="get-voice-knowledge-base-agent-id-gaps" 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 |  |
| `data.gaps` | object[] |  |

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

| Field | Type | Description |
| --- | --- | --- |
| `_id` | string | MongoDB document id, included because every document has one; use gapId to identify it. |
| `gapId` | string | Server-generated. Immutable. |
| `agentId` | string |  |
| `query` | string | The caller question that triggered a low-confidence or hedging KB answer. |
| `context` | string |  |
| `avgRetrievalScore` | number |  |
| `conversationId` | string | The call this gap surfaced from. See Conversations. |
| `suggestedTitle` | string |  |
| `suggestedAnswer` | string | AI-drafted answer. Override with title/answer in the request body when adding to the KB. |
| `status` | string | One of: `pending`, `added`, `dismissed` . |
| `severity` | string | One of: `low`, `medium`, `high` . |
| `resolvedAt` | string (date-time) |  |
| `createdAt` | string (date-time) |  |
| `updatedAt` | string (date-time) |  |

</details>

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"gaps": [
  {
    "gapId": "gap-4f1a",
    "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "query": "Do you offer a student discount?",
    "avgRetrievalScore": 0.31,
    "conversationId": "c9d8e7f6-a5b4-3210-9876-543210fedcba",
    "suggestedTitle": "Student discount policy",
    "suggestedAnswer": "We don't currently offer a student discount.",
    "status": "pending",
    "severity": "medium",
    "resolvedAt": null,
    "createdAt": "2026-08-01T12:00:00.000Z",
    "updatedAt": "2026-08-01T12:00:00.000Z"
  }
]
  }
}
```

</div>

</ResponsePanel>

</div>

<h2 id="delete-voice-knowledge-base-agent-id-gaps-gap-id">Dismiss Gap</h2>

#### Dismiss Gap

Requires the OWNER or ADMIN role. Marks the gap dismissed without writing anything to the knowledge base.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |
| `gapId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X DELETE 'https://api.speakai.co/v1/voice/knowledge-base/AGENT_ID/gaps/GAP_ID' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="delete-voice-knowledge-base-agent-id-gaps-gap-id" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Gap not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "Gap dismissed"
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` Gap not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Gap not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-voice-knowledge-base-agent-id-gaps-gap-id-add">Add Gap To KB</h2>

#### Add Gap To Knowledge Base

Requires the OWNER or ADMIN role. Writes the gap's answer (or your override) into the agent's knowledge base as a new document, and marks the gap added. Fails with 409 if the gap was already added or dismissed, or if the agent has no knowledge base collection to write into.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |
| `gapId` | path | string | Yes |  |

### 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 |
| --- | --- | --- |
| `answer` | string | Overrides suggestedAnswer. Optional. |
| `title` | string | Overrides suggestedTitle. Optional. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/knowledge-base/AGENT_ID/gaps/GAP_ID/add' \
  -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-voice-knowledge-base-agent-id-gaps-gap-id-add" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Gap not found"},{"code":"409","description":"Conflict"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "Added to knowledge base"
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` Gap not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Gap not found",
  "hints": []
}
```

</div>

<div slot="status-409">

**`409` Conflict**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "Gap already resolved"
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-voice-knowledge-base-agent-id-gaps-analyze">Analyze KB Gaps</h2>

#### Analyze KB Gaps

Requires the OWNER or ADMIN role. Triggers gap analysis over this agent's recent calls in the background and returns immediately -- new gaps appear in the list once analysis finishes, which is not synchronous with this response.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/knowledge-base/AGENT_ID/gaps/analyze' \
  -H 'x-speakai-key: sk_test_speak_0000000000000000' \
  -H 'x-access-token: eyJhbGciOiJIUzI1NiJ9.test-access-token.0000000000'
```

</CodePanel>

<ResponsePanel id="post-voice-knowledge-base-agent-id-gaps-analyze" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Agent not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "success",
  "message": "Analysis started"
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` Agent not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Agent not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

## Instruction Gaps

<h2 id="post-voice-agents-agent-id-generation-gaps-analyze">Analyze Instruction Gaps</h2>

#### Analyze Instruction Gaps

Requires the OWNER or ADMIN role. Advisory only -- compares the agent's current instructions against anchors/original intent/conversation summaries you supply and suggests up to 3 patches. Nothing is written; pass a suggestion's suggestedPatch to Apply Instruction Gap to actually apply it.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |

### 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 |
| --- | --- | --- |
| `anchors` | string[] | Specific requirements the instructions must cover. Defaults to empty. |
| `originalPrompt` | string | The original generation prompt, for context. |
| `conversationSummaries` | string[] | Recent call summaries, to ground suggestions in what actually came up. Defaults to empty. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/agents/AGENT_ID/generation/gaps/analyze' \
  -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-voice-agents-agent-id-generation-gaps-analyze" statuses={[{"code":"200","description":"OK"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Agent not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |
| `data.gaps` | object[] | Up to 3 suggestions. Nothing is persisted by this endpoint. |

<details>
<summary>`data.gaps` -- 4 more fields</summary>

| Field | Type | Description |
| --- | --- | --- |
| `description` | string |  |
| `suggestedPatch` | string | Pass this straight into Apply Instruction Gap's suggestedPatch. |
| `insertAfterSection` | string |  |
| `severity` | string | One of: `low`, `medium`, `high` . |

</details>

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"gaps": [
  {
    "description": "No guidance for refund requests",
    "suggestedPatch": "If the caller asks about a refund, explain the 30-day policy and offer to transfer to billing.",
    "insertAfterSection": null,
    "severity": "medium"
  }
]
  }
}
```

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` Agent not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Agent not found",
  "hints": []
}
```

</div>

</ResponsePanel>

</div>

<h2 id="post-voice-agents-agent-id-generation-gaps-apply">Apply Instruction Gap</h2>

#### Apply Instruction Gap

Requires the OWNER or ADMIN role. Inserts suggestedPatch into the agent's instructions (after insertAfterSection if given, otherwise appended) and persists the result.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `agentId` | path | string | Yes |  |

### 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 |
| --- | --- | --- |
| `suggestedPatch` | string, **required** | Required. Typically taken directly from Analyze Instruction Gaps. |
| `insertAfterSection` | string | Insert after this named section heading; omit or null to append at the end. |

<div slot="code">

<CodePanel label="Example request">

```bash
curl -X POST 'https://api.speakai.co/v1/voice/agents/AGENT_ID/generation/gaps/apply' \
  -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-voice-agents-agent-id-generation-gaps-apply" statuses={[{"code":"200","description":"OK"},{"code":"400","description":"suggestedPatch is required"},{"code":"403","description":"Caller's role is not OWNER or ADMIN"},{"code":"404","description":"Agent not found"}]}>

<div slot="status-200">

**`200` OK**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `success` . |
| `data` | object |  |
| `data.instructions` | string | The agent's full instructions after the patch was applied. |

Example response, `application/json`.

```json
{
  "status": "success",
  "data": {
"instructions": "You are a helpful support agent...\n\nIf the caller asks about a refund, explain the 30-day policy and offer to transfer to billing."
  }
}
```

</div>

<div slot="status-400">

**`400` suggestedPatch is required**

Response body, `application/json`.

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

</div>

<div slot="status-403">

**`403` Caller's role is not OWNER or ADMIN**

Response body, `application/json`.

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

Example response, `application/json`.

```json
{
  "status": "failed",
  "message": "You do not have permission to manage agents"
}
```

</div>

<div slot="status-404">

**`404` Agent not found**

Response body, `application/json`.

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | One of: `failed` . |
| `requestId` | string |  |
| `code` | integer |  |
| `message` | string |  |
| `hints` | string[] |  |

Example response, `application/json`.

```json
{
  "status": "failed",
  "code": 404,
  "message": "Agent not found",
  "hints": []
}
```

</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-voice-agents/intelligence).

Source: https://docs.speakai.co/api/voice-agents/intelligence/index.mdx
