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

# Web widgets API

> Manage widgets and use the public widget runtime endpoints.

A web widget is the embeddable configuration that connects a published agent version to your website. The API has two parts: authenticated management endpoints under `/core/web-widgets` that you call from your backend to create and configure widgets, and unauthenticated public runtime endpoints under `/core/public/web-widgets` that the embedded widget calls from the browser to start conversations.

For the product walkthrough and the embed snippet, see [/web-widgets/overview](/web-widgets/overview). For domain restrictions, see [/web-widgets/allowed-domains-and-security](/web-widgets/allowed-domains-and-security).

## Authentication

The management endpoints require a token with the right scope. Use an org API key (`ak_`) or a user PAT (`pat_`):

```bash theme={null}
Authorization: Bearer <token>
X-Anyreach-Org: <organization_id>   # only required for pat_ tokens
```

| Scope                | Grants                                         |
| -------------------- | ---------------------------------------------- |
| `web_widgets:read`   | List and read widgets                          |
| `web_widgets:manage` | Create, update, delete, and auto-brand widgets |

Read endpoints accept either scope. Write endpoints (`POST`, `PUT`, `DELETE`, auto-brand) require `web_widgets:manage`.

<Warning>
  The public runtime endpoints are unauthenticated and resolve the organization from the widget `id` in the path. They are meant to be called from the browser by the embedded widget. Never send a PAT, API key, or `X-Anyreach-Org` header from browser code.
</Warning>

## Management endpoints

All paths below are prefixed with `/core/web-widgets`.

| Method   | Path                                | Scope                | Description                     |
| -------- | ----------------------------------- | -------------------- | ------------------------------- |
| `GET`    | `/core/web-widgets`                 | `web_widgets:read`   | List widgets                    |
| `POST`   | `/core/web-widgets`                 | `web_widgets:manage` | Create a widget                 |
| `GET`    | `/core/web-widgets/{id}`            | `web_widgets:read`   | Get one widget                  |
| `PUT`    | `/core/web-widgets/{id}`            | `web_widgets:manage` | Update a widget                 |
| `DELETE` | `/core/web-widgets/{id}`            | `web_widgets:manage` | Delete a widget (returns `204`) |
| `POST`   | `/core/web-widgets/{id}/auto-brand` | `web_widgets:manage` | Fetch brand data for a domain   |

### Widget object

Every read and write endpoint returns the widget object.

| Field              | Type      | Description                                               |
| ------------------ | --------- | --------------------------------------------------------- |
| `id`               | string    | Widget identifier (used in the embed and in public paths) |
| `organization_id`  | string    | Owning organization                                       |
| `agent_id`         | string    | Agent the widget serves                                   |
| `agent_version_id` | string    | The specific agent version the widget runs                |
| `domains`          | string\[] | Domains allowed to embed and call the widget              |
| `published`        | boolean   | Whether the widget is live                                |
| `config`           | object    | Widget appearance and behavior configuration              |
| `created_at`       | datetime  | Creation timestamp                                        |
| `updated_at`       | datetime  | Last update timestamp                                     |

### List widgets

`GET /core/web-widgets`

Returns an array of widgets. All query parameters are optional.

| Parameter          | Type     | Description               |
| ------------------ | -------- | ------------------------- |
| `agent_id`         | string   | Filter by agent           |
| `agent_version_id` | string   | Filter by agent version   |
| `published`        | boolean  | Filter by published state |
| `created_after`    | datetime | Created at or after       |
| `created_before`   | datetime | Created at or before      |
| `updated_after`    | datetime | Updated at or after       |
| `updated_before`   | datetime | Updated at or before      |
| `limit`            | integer  | Page size                 |
| `cursor`           | string   | Pagination cursor         |

### Create a widget

`POST /core/web-widgets`

The body sets the agent and version the widget runs. `organization_id` is taken from your token, not the body.

| Field              | Type      | Default  | Description                |
| ------------------ | --------- | -------- | -------------------------- |
| `agent_id`         | string    | required | Agent to serve             |
| `agent_version_id` | string    | required | Agent version to run       |
| `domains`          | string\[] | `[]`     | Allowed embed domains      |
| `published`        | boolean   | `false`  | Whether the widget is live |
| `config`           | object    | `{}`     | Widget configuration       |

```bash theme={null}
curl -X POST https://api.anyreach.ai/core/web-widgets \
  -H "Authorization: Bearer ak_..." \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agt_...",
    "agent_version_id": "av_...",
    "domains": ["app.example.com"],
    "published": true
  }'
```

<Note>
  The widget runs whatever `agent_version_id` you give it. Point it at a published agent version so the embedded widget can dispatch real conversations. See [/web-widgets/overview](/web-widgets/overview) for how versions are published.
</Note>

### Update a widget

`PUT /core/web-widgets/{id}`

Send only the fields you want to change. `agent_id`, `agent_version_id`, `domains`, `published`, and `config` are all optional and replace the stored value when present.

### Delete a widget

`DELETE /core/web-widgets/{id}`

Returns `204 No Content` on success.

### Auto-brand

`POST /core/web-widgets/{id}/auto-brand`

Fetches brand data (colors, logos, and related assets) for a domain so you can pre-fill widget styling. The widget must exist.

| Field    | Type   | Description                                                                        |
| -------- | ------ | ---------------------------------------------------------------------------------- |
| `domain` | string | Domain to look up. Protocol, `www.`, and trailing slash are stripped automatically |

Returns the resolved brand object. Responds with `404` if no brand is found for the domain.

## Public runtime endpoints

These power the embedded widget in the browser. They are unauthenticated: the organization is resolved from the widget `id` in the path, and the conversation channel is always `WEBRTC`. All paths are prefixed with `/core/public/web-widgets`.

| Method | Path                                                                     | Description                       |
| ------ | ------------------------------------------------------------------------ | --------------------------------- |
| `GET`  | `/core/public/web-widgets/{id}`                                          | Fetch widget config for rendering |
| `POST` | `/core/public/web-widgets/{id}/conversations`                            | Create or resume a conversation   |
| `GET`  | `/core/public/web-widgets/{id}/conversations`                            | List a visitor's conversations    |
| `POST` | `/core/public/web-widgets/{id}/conversations/{conversation_id}/feedback` | Submit post-conversation feedback |

### Get widget config

`GET /core/public/web-widgets/{id}`

Returns the same widget object as the management endpoints. The embedded widget uses it to render appearance and behavior.

### Create or resume a conversation

`POST /core/public/web-widgets/{id}/conversations`

Starts a new `WEBRTC` conversation, or resumes an existing one when `conversation_id` is set. The response carries the LiveKit `connection_details` the browser uses to join the call.

| Field             | Type   | Description                                                                  |
| ----------------- | ------ | ---------------------------------------------------------------------------- |
| `user_id`         | string | Visitor identifier. Required                                                 |
| `custom_metadata` | object | Optional metadata stored on the conversation                                 |
| `conversation_id` | string | Existing conversation to resume. When omitted, a new conversation is created |

When resuming, the conversation must belong to this widget or the request returns `403`; an unknown `conversation_id` returns `404`.

The response is a JSON object:

| Field                | Type   | Description                                                                                   |
| -------------------- | ------ | --------------------------------------------------------------------------------------------- |
| `conversation`       | object | The created or resumed conversation                                                           |
| `connection_details` | object | LiveKit connection info (`url`, `token`, room) for joining the WebRTC session                 |
| `capabilities`       | object | `supportsVideoInput` and `supportsScreenShare`, derived from the agent's vision configuration |

### List a visitor's conversations

`GET /core/public/web-widgets/{id}/conversations`

Lists conversations scoped to this widget. Defaults to the `WEBRTC` channel. All query parameters are optional.

| Parameter | Type    | Description                                 |
| --------- | ------- | ------------------------------------------- |
| `user_id` | string  | Filter to one visitor                       |
| `channel` | string  | Conversation channel (defaults to `WEBRTC`) |
| `ids`     | string  | Comma-separated conversation IDs            |
| `limit`   | integer | Page size                                   |
| `cursor`  | string  | Pagination cursor                           |

### Submit feedback

`POST /core/public/web-widgets/{id}/conversations/{conversation_id}/feedback`

Stores post-conversation feedback on the conversation. The conversation must already exist and belong to the widget, and the widget must have a feedback form configured.

| Field  | Type   | Description                             |
| ------ | ------ | --------------------------------------- |
| `data` | object | Feedback field values keyed by field id |

Only keys that match the widget's configured feedback-form field ids are stored; others are dropped. The endpoint enforces:

| Limit                        | Value                                   |
| ---------------------------- | --------------------------------------- |
| Max payload size             | `16 KB` (serialized JSON)               |
| Submissions per conversation | One — a second submission returns `409` |

Returns `{ "status": "ok" }` on success. It returns `400` if the widget collects no feedback or no valid fields were submitted, and `413` if the payload is too large.

## Related

<CardGroup cols={2}>
  <Card title="Web widgets" icon="window" href="/web-widgets/overview">
    Configure and embed a widget on your site.
  </Card>

  <Card title="Allowed domains and security" icon="shield" href="/web-widgets/allowed-domains-and-security">
    Restrict which sites can embed and run a widget.
  </Card>
</CardGroup>
