Перейти к содержимому

Документация

Установка занимает пять минут и не требует программиста. Разделы ниже нужны, только если вы хотите большего: узнавания авторизованных клиентов и проверки их состояния в вашем API.

Установка виджета

  1. 01 Подтвердите почту До подтверждения бот выключен намеренно: иначе спам-регистрация получала бы рабочий виджет на наш ключ к модели.
  2. 02 Загрузите базу знаний Вкладка «База знаний», перетаскивание файлов .md, .txt или .zip. Индексация идёт в фоне, её состояние видно в списке статей.
  3. 03 Укажите домен сайта Настройки, поле «Разрешённые домены». С доменов не из списка виджет не откроется.
  4. 04 Вставьте строку на сайт Скопируйте её из кабинета и поставьте перед закрывающим тегом body. Ключ в строке публичный, прятать его не нужно.
<script
  src="https://knowdesk.ru/widget/embed.js"
  data-bot-key="pk_live_xxxxxxxxxxxx"
  async></script>

Узнавание авторизованного клиента

Если посетитель уже вошёл на ваш сайт, передайте его идентификатор вместе с подписью. Бот перестанет спрашивать то, что вы уже знаете, а диагностика сможет обращаться в ваш API от имени именно этого клиента.

Подпись считается на вашем сервере секретным ключом бота и в браузер в открытом виде не попадает. Ключ лежит в кабинете: Настройки → Дополнительно → Узнавание клиента, кнопка «Показать ключ». Без подписи данные считаются непроверенными и в вызовы API не подставляются.

Что ставит на страницу ваш сайт

Объект читается не в момент загрузки скрипта, а когда посетитель первый раз открывает чат, — поэтому в одностраничном приложении его можно поставить и после строки установки, когда данные пользователя дойдут с вашего API. Порядок неважен, важно только успеть до первого открытия чата.

Дальше объект уже не перечитывается: смена значения в открытой вкладке ничего не изменит до перезагрузки страницы. Если у клиента меняется то, что вы кладёте в attributes — скажем, он переключился на другой проект, — страницу нужно перезагрузить.

<script>
  window.knowdeskIdentity = {
    external_id: "14822",           // обязателен
    email:       "client@example.com",
    name:        "Иван Петров",      // в подпись не входит
    expires_at:  1755262800,        // unix-время, обычно +1 час
    attributes:  { license: "SOFT-2231", plan: "pro" },
    signature:   "<посчитана на вашем сервере>"
  };
</script>

Как считается подпись

HMAC-SHA256 в шестнадцатеричном виде от строки, собранной через вертикальную черту: идентификатор, почта, срок годности, дальше атрибуты в виде имя=значение, отсортированные по возрастанию имени.

14822|client@example.com|1755262800|license=SOFT-2231|plan=pro

Пример на PHP

<?php
// Ключ из кабинета: Настройки → Дополнительно → Узнавание клиента.
// В браузер он не отдаётся никогда.
$secret = 'ваш ключ подписи';

$externalId = (string) $user->id;
$email      = (string) ($user->email ?? '');
$expiresAt  = time() + 3600;

// Необязательные атрибуты: то, что бот может подставить в диагностику.
$attributes = [
    'license' => 'SOFT-2231',
    'plan'    => 'pro',
];

ksort($attributes); // порядок обязан совпасть с нашим

$parts = [$externalId, $email, (string) $expiresAt];

foreach ($attributes as $name => $value)
{
    $parts[] = $name.'='.$value;
}

$signature = hash_hmac('sha256', implode('|', $parts), $secret);
?>

<script>
  window.knowdeskIdentity = <?= json_encode([
      'external_id' => $externalId,
      'email'       => $email,
      'name'        => $user->name,
      'expires_at'  => $expiresAt,
      'attributes'  => $attributes,
      'signature'   => $signature,
  ], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) ?>;
</script>

Из-за чего подпись не сходится

  • Почта и срок годности входят в подпись всегда, даже пустые. Нет почты — в строке остаётся пустое место между двумя чертами, а не пропущенное поле.
  • Имя в подпись не входит — оно ни на что не влияет и подделка его ничего не даёт.
  • Атрибуты сортируются по имени. Порядок ключей в объекте JavaScript не гарантирован, а подпись обязана совпасть побайтово.
  • Значения атрибутов — строки. Булево пишется как true или false, число — как текст; вложенные объекты и массивы отбрасываются, поэтому подписывать их нельзя.
  • Пустой список атрибутов ничего не добавляет к строке. Подписи, посчитанные до того, как вы начали передавать атрибуты, остаются рабочими.
  • Срок годности проверяется по нашим часам. Просроченная подпись — это отказ, а не молчаливое понижение до анонима.

Ограничения запроса: до 20 атрибутов, значение до 190 символов. Смена ключа в кабинете обнуляет все выданные подписи сразу.

Куда попадают переданные данные

Почта, имя и идентификатор видны оператору в карточке обращения, под заголовком «Клиент», с отметкой «Узнан вашим сайтом».

А вот attributes сами по себе не делают ничего: атрибут связывается с диагностическим полем по ключу на вкладке «Диагностика» — заведите поле с тем же ключом (sid, license) и укажите, что значение приходит из подписанных данных. Тогда бот перестанет спрашивать его у клиента и подставит в вызов вашего API, а оператор увидит значение в карточке обращения, в блоке «Данные для диагностики». Пока такого поля нет, переданный атрибут просто никуда не идёт.

Отдельной настройкой чат можно открывать только тем, чьи данные пришли с верной подписью. Это удобно для личных кабинетов, где отвечать анонимам незачем.

Диагностика через ваш API

Настройка идёт в четыре шага и живёт на вкладке «Диагностика».

  • Спецификация. Загрузите файл OpenAPI или укажите ссылку на него. Внешние ссылки внутри спецификации отклоняются до разбора: резолвер, свободно ходящий по чужим адресам, это дыра с интерфейсом загрузки файла.
  • Безопасные операции. Отметьте те, которыми боту можно пользоваться. По умолчанию не отмечено ничего, и это правильное умолчание.
  • Диагностические поля. Опишите, что бот должен узнать у клиента: название для клиента, ключ для связи с параметром, подсказку «где это взять», пример значения и шаблон проверки.
  • Привязка к клиенту. Если значение известно из проверенной подписи, укажите это. Такой параметр исчезнет из схемы инструмента, и подставить туда чужой идентификатор станет физически невозможно.

Когда значения не хватает, бот не идёт в сеть, а возвращает структурированную ошибку и спрашивает клиента. Отдельный инструмент «задать вопрос» здесь не нужен и вреден.

API обращений

Тариф Pro. Нужен, когда обращения должны жить не только в чате: список запросов в личном кабинете вашего сайта, форма «написать в поддержку» на вашей вёрстке, выгрузка в вашу отчётность. Запрос, созданный через API, попадает в ту же очередь операторов и к тому же боту — отдельной сущности «заявка» у нас нет.

Ключ выпускается в кабинете: Настройки → API. Показывается он один раз — у нас хранится только хеш. Ключ живёт на вашем сервере: он открывает всю переписку аккаунта, поэтому кросс-доменные запросы из браузера мы не разрешаем намеренно.

# обращения одного клиента, свежие сверху
curl -H "Authorization: Bearer kd_ВАШ_КЛЮЧ" \
  "https://knowdesk.ru/api/v1/conversations?external_id=14822"

# новый запрос от клиента
curl -X POST -H "Authorization: Bearer kd_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"external_id":"14822","message":"Не приходит письмо со счётом"}' \
  "https://knowdesk.ru/api/v1/conversations"

Что умеет

  • GET /api/v1/conversations — список с фильтрами: external_id (обращения одного человека), status, open, escalated, search, created_from, created_to, updated_since.
  • GET /api/v1/conversations/{id} — карточка запроса: заголовок, статус, взят ли оператором.
  • GET /api/v1/conversations/{id}/messages — переписка. Курсор after — это seq, а не время: по времени сообщения теряются.
  • POST /api/v1/conversations — новый запрос. Обязательно только message.
  • POST /api/v1/conversations/{id}/messages — реплика клиента в существующий запрос.

Что стоит знать заранее

  • Внутренние заметки операторов наружу не уходят. Они лежат в той же ленте, что и переписка, и в ответах API их нет ни при каких параметрах.
  • external_id связывает каналы. Человек, писавший в чат на сайте, и он же, заведший запрос из личного кабинета, — один посетитель с одной историей.
  • external_ref — ваш номер заявки и ключ повтора. Отправка той же ссылки второй раз вернёт уже созданный диалог с кодом 200 вместо 201, а не заведёт второй.
  • escalate: true отправляет запрос сразу человеку, минуя бота. Без него отвечает бот и передаёт разговор оператору по обычным правилам.
  • Каждый созданный запрос — диалог в вашем тарифе. Сверх лимита он всё равно создаётся и доходит до оператора, но бот на него не отвечает.

Лимиты и защита

Проверка домена от расхода бюджета не защищает: заголовок подделывается вне браузера. Поэтому кроме неё работают счётчики на посетителя и на адрес.

Длина сообщения
4000 символов
Сообщений с одного посетителя в час
30
Сообщений с одного посетителя в сутки
200
Сообщений с одного адреса в час
120

Сверх этого действуют лимиты тарифа: месячные диалоги и суточные сообщения. Подробности на странице тарифов.

Соберите бота за пять минут

Тариф Free без карты и без срока: сто диалогов в месяц, чтобы проверить продукт на своих настоящих вопросах.