---
title: "Create Chat Widget"
method: POST
path: "/settings/chat-widgets"
tags: ["Settings"]
---

# Create Chat Widget

`POST /settings/chat-widgets`

## Request

- Base URL: `https://api.openintake.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.openintake.ai/settings/chat-widgets`
- Auth: none declared

Create an additional chat widget for the current customer.

New widgets are never the default; the default is the customer's original
widget (created on first legacy update, or promoted via update).

## Request body

- CreateChatWidgetRequest: Create a new chat widget request model
  - `enabled` boolean, nullable: Whether the chat widget is shown on the customer's website
  - `accent_color` string, nullable: Primary color hex code (e.g., #B5683C)
  - `secondary_color` string, nullable: Secondary accent color hex code. Set to null to auto-derive from accent color.
  - `launcher_color` string, nullable: Launcher bubble color hex code. Set to null to use the accent color.
  - `position` string, nullable: Widget position: bottom-right or bottom-left
  - `greeting_message` string, nullable: The first message shown when a visitor opens the chat
  - `assistant_name` string, nullable: Displayed in the chat header
  - `system_prompt` string, nullable: Full system prompt override. Set to null to use assembled prompt from structured fields.
  - `persona_prompt` string, nullable: Personality/tone instructions
  - `law_firm_context` string, nullable: Firm-specific information injected into the prompt. Set to null to leave it out.
  - `fields_to_collect` FieldToCollect[], nullable: Fields to collect from visitors with lead generation requirements
    - `key` string, required: Unique field identifier (e.g. 'name', 'phone', 'email')
    - `label` string, required: Human-readable label (e.g. 'Full Name', 'Phone Number')
    - `description` string, nullable: Hint for the AI on how to collect this field
    - `required_for_lead` boolean: Whether this field must be collected before a lead can be generated
  - `intake_goal` string, nullable: What to do after collecting info
  - `additional_instructions` string, nullable: Extra rules or context
  - `teaser_enabled` boolean, nullable: Whether to show a teaser message bubble
  - `teaser_message` string, nullable: Teaser message text
  - `teaser_delay_seconds` integer, nullable: Seconds before teaser appears
  - `show_online_status` boolean, nullable: Whether to show online indicator
  - `show_unread_badge` boolean, nullable: Whether to show unread badge on bubble
  - `tab_notification_enabled` boolean, nullable: Whether to flash unread count in tab title
  - `avatar_url` string, nullable: URL of agent avatar image
  - `avatar_video_url` string, nullable: URL of a silent looping video shown in place of the avatar image (header and launcher). Takes precedence over avatar_url.
  - `avatar_video_in_header` boolean, nullable: When false, the open panel's header shows the static avatar image and the avatar video only plays on the launcher bubble
  - `launcher_avatar_enabled` boolean, nullable: When true (and avatar_url is set), the floating launcher shows the avatar image inside an accent-colored ring instead of the default chat bubble icon
  - `intro_video_enabled` boolean, nullable: When true (and intro_video_url is set), opening the widget plays an intro video full-panel before transitioning into the chat
  - `intro_video_url` string, nullable: URL of the intro video (mp4/webm) played when the widget opens
  - `intro_video_autoplay_on_load` boolean, nullable: When true, desktop visitors see the muted intro video playing in the widget corner on page load; when false it only plays after they click the launcher
  - `auto_open_on_load` boolean, nullable: When true, the chat panel opens automatically on page load for desktop visitors (>=768px wide); mobile keeps the collapsed bubble. No conversation is created until the visitor sends their first message
  - `attention_grabber_enabled` boolean, nullable: When true, a full-page modal asks visitors if they need help; Yes opens the chat directly, No dismisses it
  - `attention_grabber_message` string, nullable: Question shown in the attention grabber modal
  - `attention_grabber_delay_seconds` integer, nullable: Seconds before the attention grabber modal appears (1-120)
  - `idle_message` string, nullable: Message shown when visitor is idle
  - `idle_delay_seconds` integer, nullable: Seconds of inactivity before nudge (10-300)
  - `quick_exit_enabled` boolean, nullable: Privacy Quick Exit: the widget never persists the chat across page loads — the conversation is ended and reset on browser close/refresh
  - `phone_check_enabled` boolean, nullable: When true, the backend counts the digits of any phone number the visitor sends and tells the assistant whether it is a valid U.S. number, so the widget's prompt can ask them to double-check it
  - `mock_booking_enabled` boolean, nullable: Demo only: the widget offers a mock "book a free consultation" slot picker that books nothing (no availability lookup, meeting, or calendar event). Never served in prod, and cannot be enabled there
  - `mobile_bottom_offset_px` integer, nullable: Extra clearance in pixels between the widget and the bottom of the viewport on mobile (0-300). Null = none.
  - `chat_idle_timeout_minutes` integer, nullable: Minutes of inactivity before auto-completing a chat (1-60). Default: 10 minutes.
  - `allowed_origins` string[], nullable: Allowed origins for CORS. When empty or null, any origin can embed the widget.
  - `allow_all_origins` boolean, nullable: When true, any origin may embed the widget regardless of allowed_origins (temporary escape hatch, e.g. during onboarding)
  - `custom_domain` string, nullable: White label: customer-owned hostname serving both widget.js and /chat/* (e.g. chat.theleachfirm.com). Hostname only — no scheme, path or trailing dot. Set to null to go back to the openintake-hosted bundle.
  - `name` string, required: Display label for the widget (e.g. which website it serves)

## Response `201`

Successful Response

- ChatWidgetDetailResponse: Full configuration of a single chat widget
  - `customer_id` string, uuid, required
  - `enabled` boolean, required: Whether the chat widget is shown on the customer's website
  - `accent_color` string, required: Primary color for the bubble, header, and assistant messages
  - `secondary_color` string, nullable: Secondary accent color. When null, derived automatically from the accent color.
  - `launcher_color` string, nullable: Overrides the floating launcher bubble color only (e.g. when the accent blends into the site background). When null, the launcher uses the accent color.
  - `position` string, required: Where the chat bubble appears on the page (bottom-right or bottom-left)
  - `greeting_message` string, required: The first message shown when a visitor opens the chat
  - `assistant_name` string, required: Displayed in the chat header
  - `system_prompt` string, nullable: Full system prompt override. When set, replaces the assembled prompt entirely.
  - `persona_prompt` string, nullable: Personality/tone instructions (e.g. 'You are Ashley, a warm and professional intake specialist')
  - `law_firm_context` string, nullable: Firm-specific information injected into the prompt.
  - `fields_to_collect` FieldToCollect[], nullable: Fields to collect from visitors. Each field can be marked as required for lead generation.
    - `key` string, required: Unique field identifier (e.g. 'name', 'phone', 'email')
    - `label` string, required: Human-readable label (e.g. 'Full Name', 'Phone Number')
    - `description` string, nullable: Hint for the AI on how to collect this field
    - `required_for_lead` boolean: Whether this field must be collected before a lead can be generated
  - `intake_goal` string, nullable: What to do after collecting info (e.g. 'Let them know an attorney will follow up within 24 hours')
  - `additional_instructions` string, nullable: Extra rules or context for the AI assistant
  - `teaser_enabled` boolean: Whether to show a teaser message bubble next to the chat button
  - `teaser_message` string, nullable: Teaser message text. Falls back to greeting_message if not set.
  - `teaser_delay_seconds` integer: Seconds to wait before showing the teaser message
  - `show_online_status` boolean: Whether to show an online indicator on the chat bubble and header
  - `show_unread_badge` boolean: Whether to show an unread badge on the chat bubble
  - `tab_notification_enabled` boolean: Whether to flash unread count in the browser tab title
  - `avatar_url` string, nullable: URL of the agent avatar image for the header and messages
  - `avatar_video_url` string, nullable: URL of a silent looping video shown in place of the avatar image (header and launcher). Takes precedence over avatar_url.
  - `avatar_video_in_header` boolean: When false, the open panel's header shows the static avatar image and the avatar video only plays on the launcher bubble
  - `launcher_avatar_enabled` boolean: When true (and avatar_url is set), the floating launcher shows the avatar image inside an accent-colored ring instead of the default chat bubble icon
  - `intro_video_enabled` boolean: When true (and intro_video_url is set), opening the widget plays an intro video full-panel before transitioning into the chat
  - `intro_video_url` string, nullable: URL of the intro video (mp4/webm) played when the widget opens
  - `intro_video_autoplay_on_load` boolean: When true, desktop visitors see the muted intro video playing in the widget corner on page load; when false it only plays after they click the launcher
  - `auto_open_on_load` boolean: When true, the chat panel opens automatically on page load for desktop visitors (>=768px wide); mobile keeps the collapsed bubble. No conversation is created until the visitor sends their first message
  - `attention_grabber_enabled` boolean: When true, a full-page modal asks visitors if they need help; Yes opens the chat directly, No dismisses it
  - `attention_grabber_message` string, nullable: Question shown in the attention grabber modal. Falls back to a default when not set.
  - `attention_grabber_delay_seconds` integer: Seconds to wait before showing the attention grabber modal
  - `idle_message` string, nullable: Message shown when visitor is idle. Leave empty to disable.
  - `idle_delay_seconds` integer, nullable: Seconds of inactivity before showing the idle nudge message
  - `quick_exit_enabled` boolean: Privacy Quick Exit: the widget never persists the chat across page loads — the conversation is ended and reset on browser close/refresh
  - `phone_check_enabled` boolean: When true, the backend counts the digits of any phone number the visitor sends and tells the assistant whether it is a valid U.S. number, so the widget's prompt can ask them to double-check it
  - `mock_booking_enabled` boolean: Demo only: the widget offers a mock "book a free consultation" slot picker that books nothing (no availability lookup, meeting, or calendar event). Never served in prod, and cannot be enabled there
  - `mobile_bottom_offset_px` integer, nullable: Extra clearance in pixels between the widget and the bottom of the viewport on mobile, for sites with a fixed bottom bar. Null = none.
  - `chat_idle_timeout_minutes` integer, nullable: Minutes of inactivity before a chat is auto-completed. Default: 10 minutes.
  - `allowed_origins` string[], nullable: Allowed origins for CORS. When empty or null, any origin can embed the widget.
  - `allow_all_origins` boolean: When true, any origin may embed the widget regardless of allowed_origins (temporary escape hatch, e.g. during onboarding)
  - `custom_domain` string, nullable: White label: customer-owned hostname (e.g. chat.theleachfirm.com) serving both widget.js and /chat/*. Shapes the embed snippet only — the CloudFront distribution and certificate must be provisioned separately, and this value never reaches the public widget config.
  - `chat_widget_id` string, uuid, required
  - `name` string, required: Display label for the widget
  - `is_default` boolean, required: Whether this is the customer's default widget

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-20** `0b14aa0ec87c`: 2 info
  - added the new optional request property `phone_check_enabled`
  - added the optional property `phone_check_enabled` to the response with the `201` status
- **2026-10-20** `037cac4dd2c3`: 2 info
  - added the new optional request property `mock_booking_enabled`
  - added the optional property `mock_booking_enabled` to the response with the `201` status
- **2026-09-22** `65ad3b27b647`: 2 info
  - added the new optional request property `auto_open_on_load`
  - added the optional property `auto_open_on_load` to the response with the `201` status
- **2026-09-18** `317be3bbe003`: 2 info
  - added the new optional request property `custom_domain`
  - added the optional property `custom_domain` to the response with the `201` status
- **2026-09-07** `b883e03846c6`: 2 info
  - added the new optional request property `launcher_color`
  - added the optional property `launcher_color` to the response with the `201` status

[Operation history](https://skmtc.dev/openintake/apis/openintake-api/changes/settings/chat-widgets/post.md)

---

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