---
title: "Create Public Widget Conversation"
method: POST
path: "/core/public/web-widgets/{id}/conversations"
tags: ["Public Web Widgets"]
---

# Create Public Widget Conversation

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

## Request

- Base URL: `https://api.anyreach.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.anyreach.ai/core/public/web-widgets/{id}/conversations`
- Auth: none declared

## Path parameters

- `id` string, required

## Headers

- `X-Anyreach-Identity` string, nullable

## Request body

- WidgetConversationCreateRequest: Schema for API requests to create or resume a conversation via a widget.
  - `user_id` string, required: User ID (must be +E.164 phone number for telephony)
  - `custom_metadata` object, nullable: Optional custom metadata
  - `conversation_id` string, nullable: Existing conversation ID to resume
  - `token` string, nullable: Capability token for the conversation. Required to resume an existing conversation (issued once at creation).
  - `opened_with_user_message` boolean: The visitor opened this conversation by sending a message (e.g. clicking a suggested question), so the agent must not open it with a greeting of its own. Makes the conversation user-initiated regardless of the agent's starting_message config. Ignored on resume.
  - `identity_pending` boolean: Created without an identity token while the page's sign-in check was still running: the response carries a bind_ticket for it. Ignored on resume.
  - `identity_check` string, nullable: The check_ticket of the page's last failed sign-in check: the new conversation's Verification panel lists that check. Ignored on resume and when the conversation starts signed in.
  - `anonymous_id` string, nullable: The embed loader's anonymous visitor id. While the widget has a running experiment, the server buckets it to pick the variant (and agent version) the conversation runs under. Ignored on resume.
  - `starter_rules` unknown[], nullable: The names of the widget's conversation-starter rules that cover the page, in any order. The starting message and buttons are taken from those rules in the widget's own config, so only names travel, never text. Ignored on resume.
    - unknown
  - `page_values` object, nullable: The page values the widget read for its conversation starters (`{{name}}` in their texts), by name. Ignored on resume.
  - `locale` string, nullable: The visitor's locale as the widget resolved it (a BCP-47 tag). Kept to the widget's supported languages; ignored when the widget has none configured, and on resume.
  - `locale_source` string, nullable: What picked the locale: host, url_rule, page_lang, browser or default. Recorded with the conversation.

## Response `200`

Successful Response

- PublicConversationCreateResponse: Body of the public widget create/resume endpoint. Every key the widget branches on is named here; anything the handler happens to put on the response dict and is not named is dropped by FastAPI before it reaches the caller.
  - `conversation` PublicConversation: A conversation as an anonymous widget caller is allowed to see it. Deliberately NOT ``Conversation``/``ConversationPartial``: those carry ``agent_config``, ``trunk_config``, ``system_metadata`` and the org/agent identifiers, none of which the widget reads. ``conversation`` is the transcript (its ``items``), which the widget replays to rehydrate history. What this guarantees, and what it does not: the agent's configuration never ships from the conversation endpoints. It is NOT a claim about the public surface as a whole — ``GET /public/web-widgets/{id}`` still returns the whole ``WebWidget`` (``organization_id``, ``agent_id``, ``agent_version_id``, ``domains``, ``created_by``), so those identifiers are already readable by anyone holding a widget id. Omitting them here is defence in depth, not a boundary you can rely on; harden that route before treating them as private.
    - `id` string, nullable
    - `user_id` string, nullable
    - `channel` 'telephone' | 'webrtc' | 'email' | 'text' | 'webchat': Channel type for the conversation.
    - `duration` integer, nullable
    - `conversation` object, nullable
    - `status` 'token_created' | 'triggered' | 'ringing' | 'in_progress' | 'completed' | 'failed' | 'cancelled' | 'transferred' | 'unanswered': Status of the conversation.
    - `created_at` string, date-time, nullable
    - `updated_at` string, date-time, nullable
  - `connection_details` object, nullable
  - `capabilities` object, nullable
  - `conversation_token` string, nullable
  - `handoff` object, nullable
  - `identity_form` object, nullable
  - `transport` 'livekit' | 'http', nullable
  - `greeting` string, nullable
  - `starting_widgets` object[], nullable
  - `rejected` boolean, nullable
  - `ended` boolean, nullable
  - `identity_verified` boolean, nullable
  - `identity_bound` boolean, nullable
  - `bind_ticket` string, nullable
  - `latest_seq` integer, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/anyreach/apis/anyreach-api.md) - [All operations](https://skmtc.dev/anyreach/apis/anyreach-api/llms.txt) - [OpenAPI document](https://skmtc.dev/anyreach/apis/anyreach-api/revisions/2eddf40c8c93?raw)
