Действия: ответы из вашей собственной системы
Действие позволяет вашему боту находить что-то в вашей собственной системе прямо во время чата — где заказ, когда его доставят, подтверждено ли бронирование. Клиент спрашивает, бот собирает нужные данные, вызывает ваш API и отвечает на основе полученного, на языке клиента.
Это работает везде, где работает ваш бот: в виджете на сайте, в ссылке на бота и QR-коде, а также в приложениях для Android, iOS, React Native, Flutter и Ionic. Ничего не устанавливается и не обновляется — вызов выполняется с наших серверов, поэтому учетные данные вашего API никогда не попадают в браузер или на телефон.
Прежде чем начать: любой может общаться с вашим ботом
Ваш бот — это публичный чат. Если для просмотра заказа достаточно одного номера заказа, любой может вводить номера, пока один из них не сработает.
Бот помогает тремя способами, но ни один из них не заменяет эту проверку: он отправляет только значения, которые клиент действительно ввел, ограничивает количество запросов из одного чата или с одного адреса, и вы можете выбрать, какие поля ответа ему разрешено видеть.
Как настроить
Откройте Действия в панели и выберите Новое действие. Этот экран видят владельцы и администраторы.
- Название — для вас, например «Статус заказа».
- Когда боту это использовать? — одно предложение, как вы объяснили бы новому коллеге: «Клиент спрашивает, где его заказ или когда он прибудет».
- Адрес вашего API —
GETилиPOSTи адресhttps://. Напишите{{order_id}}там, где должно быть значение. - Что бот спрашивает у клиента — до шести значений. У каждого есть подпись вашими словами («Номер заказа»), имя, которое использует ваш API (
order_id), и тип: любой текст, число, адрес email или номер телефона. - Заголовки — ваш API-ключ или токен. Хранится в зашифрованном виде и больше не показывается.
- Передавать боту только эти поля — необязательно. Перечислите части ответа, которые бот может использовать, например
status, eta, items[].name. Все остальное отбрасывается до того, как это увидит ИИ.
Нажмите Тест, введите примерные значения — и вы увидите отправленный запрос и ровно то, что получил бы бот. Затем проверьте по-настоящему на экране Тест: «Где мой заказ 48213? Мой email — asha@example.com».
Что получает ваш API
При GET значения, которые вы поместили в адрес, подставляются, а остальные добавляются в строку запроса:
GET https://api.yourshop.com/orders/48213?email=asha%40example.comПри POST значения передаются в теле JSON:
POST https://api.yourshop.com/lookup
Content-Type: application/json
{"order_id":"48213","email":"asha@example.com"}Каждый запрос также содержит ваши собственные заголовки и эти:
| Заголовок | Что это |
|---|---|
webhook-id | Уникальный id этого запроса |
webhook-timestamp | Когда он был отправлен, в секундах |
webhook-signature | Подпись — см. ниже |
X-Keyda-Bot | Client ID вашего бота |
X-Keyda-Action | Ключ действия, например order_status |
X-Keyda-Conversation | Чат, из которого он пришел |
Что отправлять в ответ
Ответьте в течение 8 секунд в формате JSON или короткой строкой обычного текста.
- 200 с данными — бот отвечает на их основе. Делайте ответ небольшим и используйте понятные имена полей:
{"status":"shipped","eta":"2 October"}работает лучше, чем внутренние коды. - 404, если ничего не найдено — бот сообщает клиенту и просит проверить введенные данные.
- Все остальное или отсутствие ответа вовремя — бот извиняется, предлагает ваши контакты, а чат помечается для вас. Причина показывается на экране «Действия».
Редиректы не выполняются, а ответ больше 256 KB не читается.
Проверьте подпись
Запросы подписываются по стандарту Standard Webhooks, так что вы можете использовать готовую библиотеку. Ваш секрет подписи находится на экране «Действия».
Вручную: соедините id, метку времени и точное тело запроса через точки, подпишите это с помощью HMAC-SHA256, используя секрет (часть после whsec_, декодированную из base64), и сравните.
const crypto = require('crypto');
function isFromKeyda(req, rawBody, secret) {
const id = req.headers['webhook-id'];
const ts = req.headers['webhook-timestamp'];
const given = String(req.headers['webhook-signature'] || '').replace(/^v1,/, '');
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // older than 5 minutes
const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
const want = crypto.createHmac('sha256', key).update(`${id}.${ts}.${rawBody}`).digest('base64');
return given.length === want.length
&& crypto.timingSafeEqual(Buffer.from(given), Buffer.from(want));
}При запросе GET тело пустое, поэтому подписываемый текст заканчивается точкой. Используйте POST, если хотите, чтобы подпись охватывала и сами значения.
Как бот это использует
- Он спрашивает все, чего не хватает, по одному короткому вопросу за раз, и помнит, что клиент сказал ранее в чате.
- Он никогда не угадывает значение. Если клиент его не ввел, бот спрашивает.
- Один запрос на сообщение. Ваши сохраненные ответы по-прежнему в приоритете, поэтому вопрос, на который вы ответили вручную, никогда не вызывает ваш API.
- Ответы, полученные по запросу, никогда не используются повторно для другого клиента.
- Запрос считается одним ответом, как и любой другой ответ, который пишет ИИ.
В разделе Чаты под ответом, полученным по запросу, показано, какое действие выполнялось и чем оно закончилось. Введенные клиентом значения остаются в расшифровке чата и больше нигде.
Лимиты
Действия читают информацию. Не направляйте действие на адрес, который что-то меняет — отмена заказа или возврат денег требуют шага подтверждения, которого у бота пока нет.