Шаринг диалогов Shopping Assistant
Шаринг позволяет создать публичную read-only версию существующего диалога Shopping Assistant. Покупатель может отправить ссылку другому человеку, а клиентский интерфейс — показать сообщения и товарные подборки без доступа к исходному диалогу.
Публичная версия создается как неизменяемый снимок и действует 30 дней. Ее можно отозвать раньше.
Важно
shared_path ведет к публичному JSON endpoint-у Shopping Assistant API. Если покупателю нужна готовая брендированная страница, реализуйте ее в клиентском канале: получите snapshot по shared_path и отобразите сообщения и товары в интерфейсе магазина.
Как работает сценарий
- Покупатель открывает действие «Поделиться» в существующем диалоге.
- Клиент вызывает
POST /dialogs/shareс идентификаторами пользователя и диалога. - Shopping Assistant создает неизменяемый snapshot и возвращает
share_token,shared_pathи срок действия. - Получатель открывает публичную страницу клиента.
- Страница вызывает
GET /dialogs/shared/{share_token}и отображает безопасную версию диалога. - При необходимости клиент отзывает ссылку через
POST /dialogs/share/revoke.
Идентификаторы
В API шаринга используются snake_case поля. Передавайте в них те же значения, с которыми создавался исходный диалог:
tenant_id не передается в API шаринга. Shopping Assistant проверяет пару user_id + dialog_id и определяет секцию по сохраненным metadata исходного диалога. Поля tenant_id, client_id и любые другие поля вне контракта приводят к ответу 400.
Модель доступа
В текущем контракте нет отдельного заголовка авторизации для создания и отзыва ссылки. Совпадение user_id + dialog_id служит подтверждением доступа к исходному диалогу.
Перед вызовом create или revoke проверяйте в клиентском канале, что текущая сессия относится к указанному resourceId. Не раскрывайте пару resourceId + threadId в публичных URL, сторонней аналитике или общедоступных логах. Передавайте эти идентификаторы в Gravity Field только по правилам трекинга событий. Если требования проекта предусматривают отдельную серверную авторизацию, вызывайте API шаринга через backend клиента.
POST /dialogs/share
Создает новую публичную версию диалога.
Запрос
curl --request POST \
--url 'https://shopping-assistant-api.gravityfield.ai/dialogs/share' \
--header 'Content-Type: application/json' \
--data '{
"user_id": "665f0a000000000000000001",
"dialog_id": "thread-8f2b1c",
"through_message_id": "shopping:assistant:8a21..."
}'
Можно указать ID сообщения пользователя или ассистента. Сообщение должно принадлежать исходному диалогу.
Ответ
API возвращает 201 Created:
{
"share_token": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"shared_path": "/dialogs/shared/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"through_message_id": "shopping:assistant:8a21...",
"expires_at": "2026-09-25T12:00:00.000Z"
}
Каждый успешный запрос создает отдельный snapshot. Новые сообщения исходного диалога не изменяют уже созданную публичную версию.
GET /dialogs/shared/{share_token}
Возвращает публичную версию диалога. Для запроса не нужны user_id, dialog_id или tenant_id: доступ определяется наличием действующего токена.
Ответ
{
"created_at": "2026-08-26T12:00:00.000Z",
"expires_at": "2026-09-25T12:00:00.000Z",
"messages": [
{
"role": "user",
"created_at": "2026-08-26T11:59:50.000Z",
"content": "Подбери беговые кроссовки для ежедневных тренировок"
},
{
"role": "assistant",
"created_at": "2026-08-26T12:00:00.000Z",
"response": {
"contents": [
{
"type": "message",
"value": "Вот несколько подходящих вариантов."
},
{
"type": "products",
"title": "Для ежедневных пробежек",
"categories": ["Спорт", "Беговые кроссовки"],
"value": [
{
"sku": "SKU-123",
"category_id": "42",
"name": "Runner Pro",
"price": 12990,
"features": "Амортизация; нейтральная пронация",
"brand": "Example",
"url": "https://shop.example/products/SKU-123",
"image_url": "https://cdn.example/SKU-123.jpg"
}
]
}
]
}
}
]
}
Контракт публичной версии
type SharedDialogResponse = {
created_at: string;
expires_at: string;
messages: Array<
| {
role: "user";
created_at: string;
content: string;
}
| {
role: "assistant";
created_at: string;
response: {
contents: Array<
| { type: "message"; value: string }
| {
type: "products";
title?: string;
categories?: string[];
value: SharedProduct[];
}
>;
};
}
>;
};
type SharedProduct = {
sku?: string;
category_id?: string;
name: string;
price?: number | null;
features?: string;
brand?: string;
url?: string;
image_url?: string;
};
В публичную версию не попадают:
- идентификаторы пользователя, диалога и сообщений;
- изображения, загруженные пользователем;
- кнопки и быстрые ответы;
- оценки ответов;
- latency и tracking events;
- внутренние и служебные поля товарных блоков.
Публичный токен нельзя использовать для продолжения или изменения исходного диалога.
POST /dialogs/share/revoke
Отзывает публичную ссылку.
API отзывает ссылку только при совпадении user_id, dialog_id и share_token. Ответ 204 No Content возвращается и после успешного отзыва, и если такая связка не существует. Повторный отзыв безопасен и также возвращает 204.
После отзыва GET /dialogs/shared/{share_token} возвращает 404.
Ошибки и ограничения
Лимиты API:
- создание и отзыв — до 20 запросов в минуту с одного IP;
- создание — дополнительно до 5 ссылок в минуту для одного диалога;
- получение — до 60 запросов в минуту с одного IP;
- неуспешное получение — до 10 запросов в минуту с одного IP.
Все ответы используют Cache-Control: no-store. Не кешируйте snapshot в общем кеше и не передавайте share_token в аналитику, error tracking или прикладные логи.
Рекомендации для интерфейса
- Показывайте действие «Поделиться» только после появления хотя бы одного сообщения в диалоге.
- Если пользователь выбирает конкретный ответ, передавайте его ID как
through_message_id. - Для публичной страницы предусмотрите состояния загрузки, недоступной ссылки и ошибки сети.
- Ссылки товаров открывайте по значениям
urlиз snapshot-а. - Не показывайте на публичной странице элементы продолжения диалога, оценки или внутренние действия исходного чата.
- Можно предложить получателю начать новый диалог, но для него нужно создать новые
threadIdиresourceId; продолжать исходный диалог по публичному токену нельзя. - После отзыва ссылки обновляйте состояние интерфейса, не проверяя существование токена по ответу revoke endpoint-а.
Связанные материалы