Первые экраны (welcome)
Приветственный экран — первое, что видит посетитель чата: заголовок, поле ввода, кнопки и секции с агентами. У одного ассистента таких экранов может быть несколько, у каждого своя ссылка.
Как устроены экраны
Приветственный экран собирается из трёх частей: тексты (заголовок, подзаголовок, плейсхолдер поля ввода, строка в шапке), плоский ряд кнопок quick_actions и секции welcome_sections. Секция сама карточек не хранит: она выбирает агентов ассистента по категории и показывает первых N в порядке agents.order. Добавили агенту категорию — он появился во всех секциях с этой категорией.
У ассистента есть два метода с пересекающимися данными:
| Метод | Что правит | Когда брать |
|---|---|---|
/welcome | welcome-поля самого ассистента | простые ассистенты с одним экраном, старые интеграции |
/welcome-screens | отдельные экраны со своими ссылками | несколько входов, переводы, всё, что шире заголовка и секций |
Чат читает приветствие из основного экрана (is_default: true в /welcome-screens). Поля ассистента — только источник для него: PUT /welcome записывает поля ассистента и тут же копирует в основной экран ровно те поля, что пришли в запросе. Обратного копирования нет: правка основного экрана через PUT /welcome-screens/{id} видна посетителям, но GET /welcome продолжит отдавать старое значение. Сверяйте результат по GET /welcome-screens.
Поля приветствия
Общие для ассистента и для экрана. Проверяются одними и теми же правилами в PUT /welcome, PUT /bot и /welcome-screens.
| Свойство | Тип | Описание |
|---|---|---|
welcome_message | string | Заголовок экрана, до 500 знаков. |
welcome_subtitle | string | Подзаголовок, до 500 знаков. |
header_note | string | Строка по центру шапки чата (дисклеймер), до 300 знаков. Видна только на приветственном экране. |
input_placeholder | string | Плейсхолдер поля ввода, до 255 знаков. |
welcome_mode | string | new_chat (по умолчанию) — показывать экран; message — открыть чат сразу с сообщением ассистента из welcome_start_message. У ассистента null возвращает new_chat. |
welcome_start_message | string | Первое сообщение ассистента для режима message, до 2000 знаков. У экрана — обычное поле. У ассистента хранится только по языкам, в welcome_locales.<код>.welcome_start_message; на верхнем уровне PUT /welcome и PUT /bot его не пишут и возвращают в ignored. |
welcome_avatar | string | Картинка над заголовком: путь загруженного файла (/storage/welcome-cards/…), до 1024 знаков. null или пустая строка снимает. |
welcome_collapsed_limit | int | Сколько карточек видно до кнопки «Показать больше», 1–999. 999 (по умолчанию у ассистента) — кнопки нет. У ассистента null возвращает 999, у экрана null — как у ассистента. |
welcome_sections | array | Секции экрана, до 10. См. раздел «Секции». |
welcome_locales | object | Переводы по кодам языков. См. раздел «Переводы». |
В welcome_message, welcome_subtitle и input_placeholder работают маркеры переноса строки: | — перенос всегда, || — только на телефоне, \\ — только на компьютере.
Картинку для welcome_avatar сначала загружают через POST /assistants/{assistantId}/upload/image (см. Загрузка файлов).
Кнопки под полем ввода
quick_actions — плоский ряд кнопок-подсказок под полем ввода, до 10 штук. Массив заменяется целиком.
| Свойство | Тип | Описание |
|---|---|---|
label | string | Текст кнопки, обязателен, до 50 знаков. |
prompt | string | Сообщение, которое уйдёт по клику, до 500 знаков. |
icon | string | Имя иконки Lucide в kebab-case (file-text, globe), до 50 знаков. |
action | string | Что делает клик: send (по умолчанию), image, document, diagram, voice, plot, search. |
Секции
Тип секции задаёт поле type. Без него секция считается list.
| Тип | Что показывает |
|---|---|
list | Заголовок и агентов одной категории. Без агентов секция не рисуется. |
categories | Строку вкладок-категорий, под ней агентов выбранной вкладки. Вкладка без агентов всё равно видна, под ней пустое состояние. |
templates | Блок «Шаблоны документов»: карточки агентов категории (или образцов из каталога документов) и последней — карточку-ссылку. |
Свойства секции
| Свойство | Тип | Описание |
|---|---|---|
type | string | list (по умолчанию), categories, templates. |
title | string | Заголовок над секцией, до 100 знаков. Необязателен. |
category | string | Категория агентов, до 64 знаков. Обязательна для list и templates. __all__ — все агенты ассистента. |
categories | array | Вкладки для categories: непустой список строк или объектов (см. ниже). |
limit | int | Сколько карточек показать (в categories — на каждой вкладке), 1–100, по умолчанию 6. |
display | string | row — лента с прокруткой вбок, grid — плитка вниз. Не задано — лента у categories и крупных карточек, перенос у остальных. |
align | string | Выравнивание строки вкладок: start (по умолчанию) или center. |
tabs_style | string | Вид вкладок: pills (по умолчанию) или underline. Цвет активной — primary_color ассистента. |
hidden | bool | Скрыть секцию на экране. В переводе действует только на этом языке. |
link_label | string | Только templates: подпись карточки-ссылки, до 100 знаков. |
link_url | string | Только templates: адрес карточки-ссылки, до 1024 знаков: http(s)://… или относительный, начинающийся с /, ? или #. Без пробелов. |
samples | array | Только templates: до 100 идентификаторов образцов из каталога документов ([A-Za-z0-9_-], до 120 знаков). Задан — карточки берутся из каталога, а не из агентов категории. |
link_label и link_url задаются парой: одно без другого — ошибка 422.
Вкладка в categories — строка (подпись равна ключу) или объект:
| Свойство | Тип | Описание |
|---|---|---|
category | string | Ключ категории, обязателен, до 64 знаков. Не переводится. |
label | string | Подпись вкладки, до 100 знаков. Может быть пустой — тогда на вкладке только иконка. |
icon | string | Имя иконки Lucide или эмодзи, до 64 знаков. Рисуется перед подписью. |
subcategories | array | Второй уровень внутри вкладки, до 12 групп: строки или объекты {category, label}. Агент попадает в группу, если у него есть и категория вкладки, и ключ группы. |
Если у объекта нет ни label, ни icon, подписью становится ключ. Вкладки без ключа и повторы ключей отбрасываются. Первой в строке подкатегорий фронт сам ставит «Все».
Какие категории у агента — задаётся полем categories агента: Агенты. Подписи вкладок в каталоге «Помощники» настраиваются отдельно: Каталог «Помощники».
{
"welcome_sections": [
{"title": "С чего начать", "category": "Под инпутом", "limit": 4},
{
"type": "categories",
"categories": [
{"category": "__all__", "label": "Все", "icon": "sparkles"},
"Изображения",
{"category": "Фотосессия", "label": "Фотосессия", "subcategories": ["Студия", "Путешествия"]}
],
"align": "center",
"tabs_style": "underline",
"display": "grid",
"limit": 30
},
{"type": "templates", "title": "Шаблоны документов", "category": "Шаблоны", "limit": 8,
"link_label": "Все шаблоны", "link_url": "?lib=samples"}
]
}
welcome_sections всегда заменяется целиком: чтобы добавить секцию, пришлите весь массив.
Переводы
welcome_locales — объект «код языка → набор полей»: welcome_message, welcome_subtitle, header_note, welcome_start_message, input_placeholder, welcome_sections. Языки, которых нет в списке языков ассистента, молча отбрасываются. Базовые поля (без перевода) считаются текстом на языке ассистента по умолчанию.
Правила, которые важно знать:
welcome_localesсливается с сохранённой картой по языкам и по полям — одинаково вPUT /welcome,PUT /botиPUT /welcome-screens/{id}. Не присланный язык остаётся как был; в присланном языке меняются только присланные поля;"de": nullудаляет перевод на этом языке. У нового языка не присланные поля сохраняются пустыми строками.welcome_sectionsвнутри языка — одно поле: если прислано, заменяется целиком.- В
welcome_sectionsперевода кладут тот же набор секций в том же порядке, с теми жеtypeиcategory: правила проверки те же, что у базовых секций, иначе 422. Из перевода берутся толькоtitle,labelвкладок и подкатегорий (сопоставляются по ключу категории) иhidden. Ключи, иконки,limit,display,align,tabs_style,link_labelиlink_urlвсегда берутся из базовых секций. - Язык посетителя выбирается так: точный перевод → базовые поля, если посетитель говорит на языке ассистента → перевод
en, если английский включён у ассистента → базовые поля. Пустое поле перевода на чужом языке остаётся пустым, и фронт подставляет текст из своего словаря.
Точечно переводить отдельные строки удобнее методом /i18n: Языки и переводы.
Приветствие ассистента
Получить приветствие ассистента
Отдаёт welcome-поля ассистента вместе с аватаром, режимом входа и переводами. Посетитель видит основной экран, поэтому после правок экрана напрямую сверяйтесь с GET /welcome-screens.
GET /assistants/{assistantId}/welcome
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | int | да | Путь. Id ассистента. |
curl -s "$BASE/assistants/$ASSISTANT/welcome" \
-H "Authorization: Bearer $KEY"
{
"success": true,
"welcome_message": "Чем могу помочь?",
"welcome_subtitle": "",
"header_note": "",
"input_placeholder": "Напишите сообщение…",
"quick_actions": [],
"welcome_sections": [
{"limit": 6, "title": null, "category": "Под инпутом"},
{"limit": 8, "title": "Создайте изображения", "category": "Создайте изображения"}
],
"welcome_collapsed_limit": 999,
"welcome_avatar": null,
"welcome_mode": "new_chat",
"welcome_locales": {
"de": {
"welcome_message": "Womit kann ich helfen?",
"welcome_subtitle": "",
"header_note": "",
"welcome_start_message": "",
"input_placeholder": "Nachricht schreiben…",
"welcome_sections": ["…"]
},
"…": "…"
}
}
Нет переводов — welcome_locales приходит пустым объектом {}.
| HTTP | Когда |
|---|---|
| 404 | Ассистента нет или нет доступа: {"success": false, "error": "Project not found or access denied"}. |
Изменить приветствие ассистента
Сохраняет присланные поля у ассистента и копирует их в основной экран. Не присланные поля не меняются.
PUT /assistants/{assistantId}/welcome
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | int | да | Путь. Id ассистента. |
welcome_message | string | нет | Тело. До 500. |
welcome_subtitle | string | нет | Тело. До 500. |
header_note | string | нет | Тело. До 300. |
input_placeholder | string | нет | Тело. До 255. |
quick_actions | array | нет | Тело. До 10 кнопок, заменяется целиком. |
welcome_sections | array | нет | Тело. До 10 секций, заменяется целиком. |
welcome_collapsed_limit | int | нет | Тело. 1–999, null — вернуть 999. |
welcome_avatar | string | нет | Тело. До 1024, null или "" снимает. То же поле принимает PUT /bot. |
welcome_mode | string | нет | Тело. new_chat или message, null — вернуть new_chat. |
welcome_locales | object | нет | Тело. Переводы, сливаются по языкам и полям, "<код>": null удаляет язык. |
strict | bool | нет | Тело или строка запроса. true — незнакомые и не хранимые поля дают 422, ничего не пишется. |
welcome_start_message на верхнем уровне у ассистента не хранится: метод его не пишет и возвращает в ignored. Стартовое сообщение режима message задаётся по языкам — welcome_locales.<код>.welcome_start_message.
curl -s -X PUT "$BASE/assistants/$ASSISTANT/welcome" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"welcome_message": "Чем могу помочь?",
"quick_actions": [
{"label": "Цены", "prompt": "Покажи цены", "icon": "file-text", "action": "send"}
]
}'
{
"success": true,
"applied": ["welcome_message", "quick_actions"],
"ignored": [],
"message": "Welcome updated"
}
applied — записанные поля, ignored — незнакомые и не хранимые. Если ignored не пуст, в ответе есть ещё warning: "Some fields were ignored: welcome_start_message".
| HTTP | Когда |
|---|---|
| 404 | Ассистента нет или нет доступа. |
| 422 | Ошибка проверки: {"success": false, "errors": {…}}. |
| 422 | strict=true и есть незнакомые поля: {"success": false, "error": "unknown_fields", "message": "Unknown fields: welcome_start_message", "ignored": ["welcome_start_message"]}. |
Пример ошибки проверки — неизвестный режим и лимит вне диапазона:
{
"success": false,
"errors": {
"welcome_mode": ["The selected welcome mode is invalid."],
"welcome_collapsed_limit": ["The welcome collapsed limit field must be at least 1."]
}
}
Секция templates с подписью, но без адреса:
{
"success": false,
"errors": {
"welcome_sections": ["Секция #1: ссылочная карточка требует оба поля — link_label и link_url."]
}
}
Несколько экранов
Экран — отдельный вход в того же ассистента со своими текстами, секциями и партнёрским кодом. Агенты, база знаний и настройки общие.
Адрес экрана — адрес ассистента с параметром:
| Где | Адрес |
|---|---|
| Наш домен | https://framesuite.app/f/{frame_slug}?w={slug} |
| Свой домен ассистента | https://домен/?screen={slug} |
| Основной экран | тот же адрес без параметра |
?screen= работает везде наравне с ?w=; на своём домене берите screen, потому что WordPress занимает w под номер недели. Готовый адрес экрана — в поле url. Загрузчик /embed.js принимает экран параметром ?w={slug} или атрибутом data-screen="{slug}" — подробнее в Домены, Telegram, встраивание.
Правила: у ассистента всегда ровно один основной экран; первый созданный экран становится основным сам; удалить основной или последний экран нельзя. ref_code экрана ставит посетителю партнёрскую куку — сама партнёрская программа от экранов не зависит.
Свойства экрана
| Свойство | Тип | Описание |
|---|---|---|
id | int | Id экрана. |
project_id | int | Id ассистента. Поле называется project_id по историческим причинам. |
slug | string | Адрес экрана: 3–32 знака [A-Za-z0-9_-], уникален на всей платформе. Не задан — генерируется, 12 знаков. |
name | string | Внутреннее имя в списке владельца, обязательно, до 190. |
is_default | bool | Основной экран. |
ref_code | string или null | Партнёрский код, до 32 знаков. |
welcome_message … welcome_locales | Поля приветствия, см. раздел «Поля приветствия». quick_actions у экрана нет — они общие для ассистента. | |
url | string | Готовый публичный адрес: на своём домене ассистента, если он задан, иначе на framesuite.app. |
created_at, updated_at | string | ISO 8601. |
Список экранов
Основной экран идёт первым, дальше по id.
GET /assistants/{assistantId}/welcome-screens
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | int | да | Путь. |
curl -s "$BASE/assistants/$ASSISTANT/welcome-screens" \
-H "Authorization: Bearer $KEY"
{
"success": true,
"screens": [
{
"id": 10,
"project_id": 53,
"slug": "LQmAMDZFO44o",
"name": "Основной",
"is_default": true,
"ref_code": null,
"welcome_message": "Чем могу помочь?",
"welcome_subtitle": "",
"header_note": "",
"welcome_start_message": "",
"input_placeholder": "Напишите сообщение…",
"welcome_mode": "new_chat",
"welcome_collapsed_limit": null,
"welcome_avatar": null,
"welcome_sections": [
{"limit": 6, "title": null, "category": "Под инпутом"},
{
"type": "categories",
"limit": 50,
"hidden": true,
"categories": [
{"label": "Лучшие предложения", "category": "Лучшие предложения"},
{"label": "Изображения", "category": "Изображения"}
]
}
],
"welcome_locales": {
"de": {
"welcome_message": "Womit kann ich helfen?",
"welcome_subtitle": "",
"header_note": "",
"welcome_start_message": "",
"input_placeholder": "Nachricht schreiben…",
"welcome_sections": ["…"]
}
},
"url": "https://bota.chat/",
"created_at": "2026-08-10T13:09:13.000000Z",
"updated_at": "2026-09-25T18:20:50.000000Z"
},
{
"id": 115,
"slug": "x488",
"name": "Документы",
"is_default": false,
"welcome_message": "Помогу с документами",
"welcome_locales": [],
"url": "https://bota.chat/?screen=x488",
"…": "…"
}
]
}
Пустые переводы приходят как [], а не {}.
| HTTP | Когда |
|---|---|
| 404 | Ассистента нет или нет доступа. |
Получить экран
GET /assistants/{assistantId}/welcome-screens/{screenId}
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | int | да | Путь. |
screenId | int | да | Путь. Id экрана этого ассистента. |
curl -s "$BASE/assistants/$ASSISTANT/welcome-screens/115" \
-H "Authorization: Bearer $KEY"
Ответ: {"success": true, "screen": {…}} — объект как в списке.
| HTTP | Когда |
|---|---|
| 404 | Ассистента нет или нет доступа; экран другого ассистента или несуществующий: {"success": false, "error": "Welcome screen not found"}. |
Создать экран
POST /assistants/{assistantId}/welcome-screens
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | int | да | Путь. |
name | string | да | Тело. До 190. |
slug | string | нет | Тело. 3–32, [A-Za-z0-9_-], уникален. Не задан — сгенерируется. |
ref_code | string | нет | Тело. До 32. |
is_default | bool | нет | Тело. Сделать основным; у первого экрана ассистента ставится сам. |
| поля приветствия | нет | Тело. Все из раздела «Поля приветствия». |
curl -s -X POST "$BASE/assistants/$ASSISTANT/welcome-screens" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Для рекламы",
"ref_code": "promo-aug",
"welcome_message": "Разберём задачу за 5 минут",
"welcome_sections": [
{"title": "С чего начать", "category": "Под инпутом", "limit": 4},
{"type": "categories", "categories": [{"category": "__all__", "label": "Все", "icon": "sparkles"}, "Изображения"], "limit": 12}
],
"welcome_locales": {
"en": {
"welcome_message": "Let us sort it out in 5 minutes",
"welcome_sections": [
{"title": "Start here", "category": "Под инпутом"},
{"type": "categories", "categories": [{"category": "__all__", "label": "All"}, {"category": "Изображения", "label": "Images"}]}
]
}
}
}'
Ответ 201:
{
"success": true,
"screen": {
"id": 175,
"project_id": 53,
"slug": "OR3hhPch8SRK",
"name": "Для рекламы",
"is_default": false,
"ref_code": "promo-aug",
"welcome_message": "Разберём задачу за 5 минут",
"welcome_subtitle": "",
"header_note": "",
"welcome_start_message": "",
"input_placeholder": "",
"welcome_mode": "new_chat",
"welcome_collapsed_limit": null,
"welcome_avatar": null,
"welcome_sections": ["…"],
"welcome_locales": {
"en": {
"welcome_message": "Let us sort it out in 5 minutes",
"welcome_subtitle": "",
"header_note": "",
"welcome_start_message": "",
"input_placeholder": "",
"welcome_sections": ["…"]
}
},
"url": "https://bota.chat/?screen=OR3hhPch8SRK",
"created_at": "2026-09-25T19:50:59.000000Z",
"updated_at": "2026-09-25T19:50:59.000000Z"
}
}
Секции сохраняются в том виде, в каком пришли, без нормализации.
| HTTP | Когда |
|---|---|
| 404 | Ассистента нет или нет доступа. |
| 422 | Нет name, name длиннее 190, slug занят, короче 3 или длиннее 32 знаков, ref_code длиннее 32, ошибка в секциях или переводах. |
Изменить экран
Меняет только присланные поля. is_default: true переносит основной экран сюда и снимает флаг с прежнего в одной транзакции. is_default: false у основного экрана игнорируется.
PUT /assistants/{assistantId}/welcome-screens/{screenId}
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | int | да | Путь. |
screenId | int | да | Путь. |
name | string | нет | Тело. До 190. |
slug | string | нет | Тело. Смена адреса экрана: 3–32, [A-Za-z0-9_-], уникален. |
ref_code | string | нет | Тело. До 32; null снимает код. |
is_default | bool | нет | Тело. |
| поля приветствия | нет | Тело. |
curl -s -X PUT "$BASE/assistants/$ASSISTANT/welcome-screens/175" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"welcome_subtitle": "Бесплатно, без регистрации", "slug": "promo-aug"}'
Ответ: {"success": true, "screen": {…}} с обновлённым объектом, url уже с новым слагом.
Пустые name и slug ("" или null) игнорируются: обнулить их нельзя, прежние значения остаются, ответ 200. welcome_locales сливается с переводами экрана по языкам и полям, как описано в разделе «Переводы». Например, запрос ниже добавит подзаголовок в английский перевод, не тронув остальные его поля, и удалит немецкий:
curl -s -X PUT "$BASE/assistants/$ASSISTANT/welcome-screens/175" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"welcome_locales": {"en": {"welcome_subtitle": "Free"}, "de": null}}'
| HTTP | Когда |
|---|---|
| 404 | Ассистента или экрана нет. |
| 422 | Ошибка проверки, например {"success": false, "errors": {"slug": ["The slug has already been taken."]}}. |
Удалить экран
DELETE /assistants/{assistantId}/welcome-screens/{screenId}
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
assistantId | int | да | Путь. |
screenId | int | да | Путь. |
curl -s -X DELETE "$BASE/assistants/$ASSISTANT/welcome-screens/175" \
-H "Authorization: Bearer $KEY"
{"success": true}
| HTTP | Когда |
|---|---|
| 404 | Ассистента или экрана нет. |
| 422 | {"success": false, "error": "Cannot delete the last welcome screen"} — это последний экран. |
| 422 | {"success": false, "error": "Cannot delete the default welcome screen — make another screen default first"} — сначала перенесите основной экран через PUT с is_default: true. |
Сценарий: проверить экран без браузера
Первый кадр экрана — статичная разметка, которую чат рисует до загрузки скриптов. Её отдаёт публичный метод без ключа, он принимает экран и язык:
curl -s "https://framesuite.app/api/frame/{frame_slug}/first-frame?w=promo-aug&locale=en"
В ответе HTML: ищите в нём заголовок и подписи секций на нужном языке. Без w отдаётся основной экран. Если встраиваете кадр в свой сайт и кэшируете, слаг экрана и язык должны входить в ключ кэша.
Дальше
- Агенты — карточки, которые секции показывают по категориям.
- Шаблоны и подвал — юридический подвал под всеми экранами.
- Языки и переводы — языки ассистента и точечный перевод строк.