# Insights

> Every field of /v1/insights: list, create, read, change and delete what calls find out.

<!-- Generated by apps/docs/scripts/gen-reference.mjs from apps/docs/public/openapi/v1.json. Do not edit: change the API's schemas (then `pnpm --filter @seasalt/api openapi:emit`) or the notes in apps/docs/src/reference-notes/, then run `pnpm --filter @seasalt/docs gen:reference`. -->

What each call should find out, as typed fields (Dialog Insights in the dashboard); its answers are a call's `extracted`. How-to: [Choose what calls find out](/platform-api/insights/).

Generated from [`/openapi/v1.json`](/openapi/v1.json); interactive version: [API reference](/openapi/v1/).

## Endpoints

| method | path | what it does | success |
|---|---|---|---|
| [`GET`](#get-v1insights) | `/v1/insights` | List insights: what calls find out | `200` |
| [`POST`](#post-v1insights) | `/v1/insights` | Create an insight | `201` |
| [`GET`](#get-v1insightsid) | `/v1/insights/{id}` | Read an insight, with its fields | `200` |
| [`PATCH`](#patch-v1insightsid) | `/v1/insights/{id}` | Change an insight | `200` |
| [`DELETE`](#delete-v1insightsid) | `/v1/insights/{id}` | Delete an insight and detach it everywhere | `200` |

## `GET /v1/insights`

List insights: what calls find out.

The workspace's insights (Dialog Insights in the dashboard), newest first, each with its field keys and where it is attached. Read one for its fields.

**Parameters**

<div class="ref-table">

| name | in | type | description |
|---|---|---|---|
| `limit` | query | integer<br>1–200 | Page size, 1 to 200 (default 50). |
| `after` | query | string | The previous page's `next_cursor`. |

</div>

**Answers** `200` with [InsightList](#insightlist). Errors use the [error envelope](/platform-api/reference/#v1error).

## `POST /v1/insights`

Create an insight.

Defines what a call should find out, as typed fields. It runs on no call until you attach it: `insight` on `PATCH /v1/agents/{id}` (the agent's calls) or on a voice campaign (that campaign's calls). Each answer then appears in the call's `extracted` under the field's `key`, shortly after the call ends. By default an `enum` or `boolean` answer also labels the conversation in the inbox. An attached insight runs once on each call that ends, and spends credits for that model run; one attached to nothing runs on no call and costs nothing. Owner and admin keys only.

**Parameters**

<div class="ref-table">

| name | in | type | description |
|---|---|---|---|
| `idempotency-key` | header | string<br>≤ 255 chars | Send one with every create. A retry with the same key makes no second insight: it answers the first one as it is now. Rules: [Idempotency](/platform-api/retries/#idempotency). |

</div>

**Request body:** [InsightCreate](#insightcreate).

**Answers** `201` with [Insight](#insight). Errors use the [error envelope](/platform-api/reference/#v1error).

## `GET /v1/insights/{id}`

Read an insight, with its fields.

**Parameters**

<div class="ref-table">

| name | in | type | description |
|---|---|---|---|
| `id` | path | string, required | The insight's `di-…` id or UUID. |

</div>

**Answers** `200` with [Insight](#insight). Errors use the [error envelope](/platform-api/reference/#v1error).

## `PATCH /v1/insights/{id}`

Change an insight.

Changes `name`, `description` or `fields` (which replaces the list whole). It applies to calls that end after the change, on every agent and campaign it is attached to (`attached`); past calls keep the answers they have. Send the `revision` you read as `expected_revision` to refuse an edit over someone else's. A request that changes nothing answers the insight as it is. Owner and admin keys only.

**Parameters**

<div class="ref-table">

| name | in | type | description |
|---|---|---|---|
| `id` | path | string, required | The insight's `di-…` id or UUID. |

</div>

**Request body:** [InsightUpdate](#insightupdate).

**Answers** `200` with [Insight](#insight). Errors use the [error envelope](/platform-api/reference/#v1error).

## `DELETE /v1/insights/{id}`

Delete an insight and detach it everywhere.

Detaches it from every agent and campaign and deletes it, in one step (`detached` counts them). Calls that already ran keep their answers. Owner and admin keys only.

**Parameters**

<div class="ref-table">

| name | in | type | description |
|---|---|---|---|
| `id` | path | string, required | The insight's `di-…` id or UUID. |

</div>

**Answers** `200` with [InsightDeleted](#insightdeleted). Errors use the [error envelope](/platform-api/reference/#v1error).

## Objects

### InsightList

<div class="ref-table">

| field | type | description |
|---|---|---|
| `object` | string, required<br>always `list` |   |
| `data` | array of [InsightListItem](#insightlistitem), required |   |
| `has_more` | boolean, required |   |
| `next_cursor` | string or null, required | Pass as `after` for the next page; `null` on the last. |

</div>

Example: see [Choose what calls find out](/platform-api/insights/).

### InsightListItem

<div class="ref-table">

| field | type | description |
|---|---|---|
| `id` | string, required |   |
| `object` | string, required<br>always `insight` |   |
| `uuid` | string, required |   |
| `name` | string, required |   |
| `description` | string or null, required |   |
| `field_count` | integer, required |   |
| `attached` | object, required | Where it is attached. Nothing attached: it runs on no call and costs nothing. |
| `attached.agents` | integer, required | Agents (not deleted) that use it. |
| `attached.campaigns` | integer, required | Campaigns that use it. |
| `revision` | string, required | Send it back as `expected_revision` to refuse an edit over a change you have not seen. |
| `created_at` | string, required |   |
| `updated_at` | string, required |   |
| `field_keys` | array of string, required | The fields' keys; read one for the fields. |

</div>

Example: see [Choose what calls find out](/platform-api/insights/).

### Insight

<div class="ref-table">

| field | type | description |
|---|---|---|
| `id` | string, required |   |
| `object` | string, required<br>always `insight` |   |
| `uuid` | string, required |   |
| `name` | string, required |   |
| `description` | string or null, required |   |
| `field_count` | integer, required |   |
| `attached` | object, required | Where it is attached. Nothing attached: it runs on no call and costs nothing. |
| `attached.agents` | integer, required | Agents (not deleted) that use it. |
| `attached.campaigns` | integer, required | Campaigns that use it. |
| `revision` | string, required | Send it back as `expected_revision` to refuse an edit over a change you have not seen. |
| `created_at` | string, required |   |
| `updated_at` | string, required |   |
| `fields` | array of [InsightField](#insightfield), required |   |

</div>

Example: see [Choose what calls find out](/platform-api/insights/).

### InsightField

One thing a call should find out. Its answer appears in the call's `extracted` under `key`.

<div class="ref-table">

| field | type | description |
|---|---|---|
| `key` | string, required |   |
| `label` | string, required |   |
| `type` | string, required<br>`enum`, `boolean`, `number`, `text` |   |
| `description` | string, required |   |
| `enum_values` | array of string |   |
| `enum_descriptions` | map of string to string |   |

</div>

Example: see [Choose what calls find out](/platform-api/insights/).

### InsightCreate

<div class="ref-table">

| field | type | description |
|---|---|---|
| `name` | string, required<br>1–200 chars |   |
| `fields` | array of [InsightFieldInput](#insightfieldinput), required<br>1–20 items | 1 to 20 fields with unique keys; all descriptions together up to 40,000 characters. |
| `description` | string or null<br>≤ 2,000 chars | A note for people (up to 2,000 characters); not read by the model. |

</div>

```json
{
  "name": "Appointment reminder",
  "description": "What each reminder call should find out.",
  "fields": [
    {
      "key": "will_attend",
      "label": "Will attend",
      "type": "enum",
      "description": "true when the person confirms they will come; false when they cancel.",
      "enum_values": [
        "work",
        "sick",
        "other"
      ],
      "enum_descriptions": {
        "work": "a job or shift clashes with the time"
      }
    }
  ]
}
```

### InsightFieldInput

<div class="ref-table">

| field | type | description |
|---|---|---|
| `key` | string, required<br>1–64 chars; pattern `^[a-z][a-z0-9_]*$` | The answer's name in a call's `extracted` (`will_attend`). snake_case, up to 64 characters, unique in the insight. |
| `type` | string, required<br>`enum`, `boolean`, `number`, `text` | `boolean` (yes/no), `number`, `text` (free text) or `enum` (one of `enum_values`). |
| `label` | string<br>1–200 chars | What the answer is called on screens (up to 200 characters). Left out, it is the key with spaces (`Will attend`). |
| `description` | string<br>≤ 8,000 chars | How to decide the answer, in your words (up to 8,000 characters): this is what makes it accurate. Empty by default. |
| `enum_values` | array of string<br>1–50 items; each 1–120 chars | Required for `enum`, and only there: 1 to 50 values (up to 120 characters each). |
| `enum_descriptions` | map of string to string<br>values ≤ 2,000 chars | For `enum` only: when to pick each value, keyed by the value exactly as in `enum_values` (up to 2,000 characters each). |

</div>

```json
{
  "key": "will_attend",
  "label": "Will attend",
  "type": "enum",
  "description": "true when the person confirms they will come; false when they cancel.",
  "enum_values": [
    "work",
    "sick",
    "other"
  ],
  "enum_descriptions": {
    "work": "a job or shift clashes with the time"
  }
}
```

### InsightUpdate

<div class="ref-table">

| field | type | description |
|---|---|---|
| `name` | string<br>1–200 chars |   |
| `description` | string or null<br>≤ 2,000 chars | `null` removes it. |
| `fields` | array of [InsightFieldInput](#insightfieldinput)<br>1–20 items | Replaces the list whole. A kept field (same `key`) sent without `label` keeps its label; one whose `key` and `type` stay also keeps the label switch and colours set in the dashboard. |
| `expected_revision` | string<br>1–64 chars | The `revision` you read. If the insight changed since, nothing is changed: `409 revision_conflict`. Without it the edit applies over any other change. |
| `acknowledge_field_changes` | boolean | `true` saves an edit that renames or removes a field that is in use (it has open requests, starts workflows, or alerts live in the dashboard). Without it such an edit is `409 field_in_use`. |

</div>

```json
{
  "fields": [
    {
      "key": "will_attend",
      "label": "Will attend",
      "type": "enum",
      "description": "true when the person confirms they will come; false when they cancel.",
      "enum_values": [
        "work",
        "sick",
        "other"
      ],
      "enum_descriptions": {
        "work": "a job or shift clashes with the time"
      }
    }
  ],
  "expected_revision": "2026-10-29T10:00:00.123456"
}
```

### InsightDeleted

<div class="ref-table">

| field | type | description |
|---|---|---|
| `id` | string, required |   |
| `object` | string, required<br>always `insight` |   |
| `deleted` | boolean, required<br>always `true` |   |
| `detached` | object, required |   |
| `detached.agents` | integer, required |   |
| `detached.campaigns` | integer, required |   |

</div>

Example: see [Choose what calls find out](/platform-api/insights/).