Что умеет TextBack API

Через TextBack API доступна вся функциональность TextBack.

Это так, поскольку мы в TextBack исповедуем принцип - dogfooding. Мы сами используем тот же самый API для работы нашего веб-интерфейса и других внутренних сервисов, которые остаются за кадром.

Некоторые методы не описаны в спецификации и они недоступны в консоли API. Это не потому, что мы хотим что-то скрыть.

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

Не все методы важны, и мы часто не успеваем добавить описание в консоль.

Некоторые методы мы хотим переработать или убрать, поэтому намеренно не добавляем их в описание.

Мы можем гарантировать, что опубликованные методы будут работать так, как описано. Неописанные методы, к сожалению, не являются частью предоставляемого нами публичного контакта и могут быть изменены или удалены без предупреждения.

Но если вы нашли нужную вам функциональность путем исследования веб-интерфейса https://my.textback.io либо каким-то другим способом, и она не описана в консоли, дайте нам знать - мы подумаем, что с этим можно сделать.

Так же мы рады любой обратной связи от вас, особенно конструктивной критике, чтобы стать более удобными и функциональными. По любым вопросам, связанным с API, можно связаться с нами через email технической поддержки support@textback.io или в любом мессенджере через виджет чата на сайте.

С чего начать?

Перед началом разработки необходимо получить доступ к API.

Мы предлагаем такой сценарий:

  • Прежде всего зарегистрируйте учетную запись TextBack на https://textback.ru/registration

  • Войдите в личный кабинет и перейдите на страницу интеграции https://my.textback.io/messaging.html#!/integration

  • Сгенерируйте токен и скопируйте в буфер

  • Сохраните API Token - он является секретом, поскольку предоставляет доступ ко всем функциям TextBack от лица вашей учетной записи

  • Исследуйте API через API Console

  • Настройте интеграцию - подключите вебхуки

Время жизни токена равно году, но для пробного бесплатного тарифа токен генерируется до окончания бесплатного тарифа, затем вам придется сгенерировать новый токен после оплаты.

Токен выпускается с теми же правами доступа, как у пользователя, создавшего токен.

Наш API разделяется на две области применения:

  1. для обращения server to server. Вы выполняете те же действия, что и доступные из личного кабинета. Такие запросы должны содержать токен доступа и выполняются от лица пользователя, выпустившего токен. Используется для управления аккаунтом, общения с пользователями через мессенджеры, произведения рассылок, просмотра статистики.

  2. для обращения из браузера посетителя сайта Используется для замены стандартных виджетов чата и подписки. API не требует токена и вызывается от лица посетителя сайта. Доступна малая часть функциональности - получение настроек виджетов, создания подписки. Для некоторых методов (подписки, начала чата) требуется авторизация пользователя в социальной сети.

Никогда не выполняйте запросы из недоверенных сред вроде веб-браузера (кроме изучения API самостоятельно в своем браузере) или мобильного приложения и не передавайте API Token никуда кроме ваших серверов.

Варианты использования

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

Полное справочное описание методов API приводится ниже в разделе Справочник по API

Отправить шаблон WhatsApp Business API

TextBack предоставляет богатую интеграцию с WhatsApp Business API. Одна из главных особенностей этого мессенджера - правило 24-часового окна: вы можете свободно общаться с клиентом в течение 24 часов после его входящего сообщения. Как только время вышло, для продолжения диалога вы можете отправить только платный шаблон, согласованный с Facebook. Актуальную стоимость 1 шаблона уточняйте у технической поддержки.

Про особенности шаблонов WhatsApp подробно написано в нашей Базе Знаний.
Все методы для работы с WhatsApp Business API описаны в этом справочнике.

Прежде всего требуется зарегистрировать шаблон - в разделе "Шаблоны WhatsApp" в Личном Кабинете или через API. В среднем, согласование шаблона занимает до 48 часов. Шаблон может иметь динамическую часть - так называемые подстановки. Например, "Вы сделали заказ {{v1}}. Примерная дата доставки - {{v2}}. Нажмите на кнопку, чтобы отследить статус заказа". В подстановке можно передать текст, число, символы. Не допускаются переносы строк и более 4 пробелов подряд.

После одобрения шаблона вы получите идентификатор шаблона - это число, которое надо запомнить и слать в методе отправки сообщения. Кроме идентификатора шаблона вам надо знать идентификатор подключенного WhatsApp в TextBack, его можно получить воспользовавшись методом Работа с каналами

Для отправки сообщения воспользуйтесь методом Отправка сообщения с передачей параметров:

  • remoteAddress - номер телефона в формате tel:+79…​, например tel:+79210000000

  • channelId - идентификатор подключенного канала WhatsApp в TextBack

  • templateId - идентификатор зарегистрированного шаблона

  • substitutions - JSON объект со значениями подстановок, поддерживается только один уровень вложенности параметров, например {"v1": "Z123", "v2": "12.01"}

Пример запроса
curl -v ${base_url}/messages -H "${auth_header}" -X POST -d "{\"channel\":\"whatsappb\",\"channelId\":2,\"remoteAddress\":\"tel:+79210000000\",\"templateId\":\"99\",\"substitutions\":{\"v1\": \"Z123\", \"v2\": \"12.01\"}}"
Пример ответа
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$value":{...},"$count":1}

Код ответа 200 сигнализирует, что метод выполнен успешно.

Код ответа 200 означает, что сообщение поставлено в очередь. Он не гарантирует, что сообщение доставлено, а тем более прочитано удаленным пользователем. Для получения статусов доставки необходимо быть подписанным на вебхуки и слушать события доставки.

Разберем пример ответа.

{
  "direction": "outbound",
  "channelId": 2,
  "channel": "whatsappb",
  "templateId": "99",
  "chatId": "103928298",
  "id": "2c12b7e7-cd40-4a9a-b828-5fd6ec6dcc72", (1)
  "sentTimestamp": 1626697806562, (2)
  "tbChatId": 10021 (3)
}
1 Уникальный идентификатор сообщения. Обязательно запишите его в БД вашей информационной системы. По идентификатору доступен трекинг статусов доставки в дальнейшем.
2 Время отправки по часам сервера
3 Идентификатор диалога в TextBack. По идентификатору диалога можно отправлять ответы и получать полную историю переписки.

Остальные поля имеют те же значения, которые мы передали, и не составляют интереса

Отправить рассылку по номеру телефона ВКонтакте

TextBack предоставляет возможность отправить сообщение пользователю ВКонтакте, зная только его номер телефона.

Эта возможность имеет ограничения:

  1. Сообщение может формироваться только по заранее утвержденному шаблону.

  2. Функциональностью не могут пользоваться некоторые виды организаций: коллекторские агентства, микрофинансовые организации, казино, производители лекарств, сигарет, алкогольной продукции, ювелирные магазины, букмекерские конторы.

  3. Сообщение должно быть реакцией пользователя на его активное действие, например, подтверждение заказа.

  4. Сообщение не должно быть рекламным.

Подробнее про сервисные сообщения ВКонтакте вы можете прочитать в нашей Базе Знаний.

Шаблон может иметь динамическую часть - так называемые подстановки. Например, "Добрый день! Спасибо за регистрацию на #event#. Ждем вас #date# по адресу #address#. До встречи!". Подстановки задаются через синтаксис #var_name#, и var_name должно состоять из набора символов [A-Za-z].

Прежде всего требуется зарегистрировать шаблон. Регистрация шаблона производится сотрудниками технической поддержки TextBack, свяжитесь с нами любым удобным способом, указанным на сайте TextBack. Регистрация шаблона занимает до 5 рабочих дней. После успешной регистрации вы получите идентификатор шаблона (его название) - это строка, которую надо запомнить и слать в методе отправки сообщения. Кроме идентификатора шаблона вам надо знать идентификатор настроенной группы в TextBack, его можно получить воспользовавшись методом Работа с каналами.

Для отправки сообщения воспользуйтесь методом Отправка сообщения с передачей параметров:

  • remoteAddress - номер телефона в формате tel:+79…​, например +79210000000

  • channelId - идентификатор подключенного канала ВКонтакте в TextBack

  • templateId - идентификатор зарегистрированного шаблона

  • substitutions - JSON-объект со значениями подстановок, поддерживается только один уровень вложенности параметров, например: {"event": "Вышивание крестиком", "date": "12.01", "address":"ул. Декабристов, 25"}

  • параметр chatId передавать не требуется, поскольку данное сообщение не является ответом на существующую переписку

Пример запроса
curl -v ${base_url}/messages -H "${auth_header}" -X POST -d "{\"channel\":\"vk\",\"channelId\":2,\"remoteAddress\":\"tel:+79210000000\",\"templateId\":\"conference_invite\",\"substitutions\":{\"event\": \"Вышивание крестиком\", \"date\": \"12.01\",\"address\": \"ул. Декабристов, 25\"}}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$value":{...},"$count":1}

Код ответа 200 сигнализирует, что метод выполнен успешно.

Код ответа 200 означает, что сообщение поставлено в очередь. Он не гарантирует, что сообщение доставлено, а тем более прочитано удаленным пользователем. Для получения статусов доставки необходимо быть подписанным на вебхуки и слушать события доставки.

Разберем пример ответа.

{
  "direction": "outbound",
  "channelId": 2,
  "channel": "vk",
  "templateId": "conference_invite",
  "chatId": "103928298",
  "id": "2c12b7e7-cd40-4a9a-b828-5fd6ec6dcc72", (1)
  "sentTimestamp": 1459439095483,(2)
  "tbChatId": 10021(3)
}
1 Уникальный идентификатор сообщения. Обязательно запишите его в БД вашей информационной системы. По идентификатору доступен трекинг статусов доставки в дальнейшем.
2 Время отправки по часам сервера
3 Идентификатор диалога в TextBack. По идентификатору диалога можно отправлять ответы и получать полную историю переписки. Остальные поля имеют те же значения, которые мы передали, и не составляют интереса

Написать свой виджет подписок

Воспользуйтесь SDK виджета подписок, который позволит выполнить полную кастомизацию внешнего вида. SDK поможет получить конфигурацию виджета, проинициализировать API мессенджеров, сформировать правильные действия на кнопки подписок.

Документация расположена по адресу https://www.npmjs.com/package/@textback%2Fnotification-widget раздел "TextBack Widget SDK"

Справочник по API

TextBack API представляет собой HTTP API построенный по принципам REST. Способ обращения клиент-серверный. Клиентом является ваш сервис, например CRM. Сервером является TextBack. Клиент выполняет HTTP-запрос, сервер возвращает ответ.

Формат запроса и ответа - JSON, тип содержимого application/json.

Сущности API и терминология

Канал

Настроенный способ общения с клиентами, например бот в Telegram или SMS-номер. Следует отличать тип канала (Telegram, ВКонтакте, SMS) и канал. Канал - это конкретный бот, конкретная группа в ВКонтакте, конкретный номер для SMS-переписки. Параметр channel - тип канала. channelId - числовой идентификатор канала. Идентификаторы уникальны только в пределах типа канала.

Диалог

это выделенный двунаправленный поток сообщений между аккаунтом в TextBack и пользователем на другой стороне - в мессенджере, в социальной сети. Во многих каналах диалог открывается только со стороны удаленного пользователя. Пока удаленный пользователь не написал боту, диалог не открыт, следовательно нельзя отправить сообщение этому пользователю. Исключение составляют каналы, поддерживающие рассылку по номеру телефона, например Viber, ВКонтакте, Whatsapp.

Взаимодействие

HTTP коды ответа

Table 1. Используются HTTP коды ответа:

Код

Описание

Почему такое произошло?

Что делать?

200

Метод отработал успешно

Все хорошо

Считать JSON-объект из тела ответа и интерпретировать согласно документации к методу

401

Аутентификация не удалась

Вы забыли передать API Token или токен не валиден (токен отозван, закончилось время жизни, аккаунт заблокирован)

Проверить, передан ли API Token, не заблокирован ли пользователь. Проверить время жизни токена на сайте https://jwt.io или другими средствами, читающими JWT (проверить поле exp). Если да, обратиться в техподдержку

402

Требуется оплата

Метод требует оплаты тарифа или дополнительного пакета услуг

Проверить, есть ли у вас оплата требуемой функциональности и не окончен ли пакет на странице https://my.textback.io/messaging.html#!/payment Если да, обратиться в техподдержку

403

Недостаточно прав для совершения вызова

Вы вызвали метод API, который требует больше прав, нежели в представленном API Token

Сгенерировать токен от лица пользователя, обладающего необходимыми правами

400

Ошибка клиента

Вероятнее всего вы запросили у сервера выполнить нечто, что не соответствует документации либо передали не совсем валидные данные

Проанализировать подкод ошибки из поля $error.sc, исправить запрос.

500

Ошибка сервера

Все плохо

К сожалению, что-то у нас сломалось. Мы записали ошибку в лог. Но если для вас ошибка является блокирующей, обратитесь в техподдержку и сообщите идентификатор запроса из заголовка X-Correlation-Id для ускорения работы по проблеме.

Если вы встретили другой код, не указанный здесь, обрабатывайте его по общему правилу:

  • 2XX коды - запрос был успешным

  • 301, 302 - проследуйте редиректу

  • остальные коды - запрос был неуспешным. Проанализируйте код ответа самостоятельно или обратитесь в группу развития API

Формат успешного ответа

Мы отдаем ответ в обертке вида

{
    "$count": 1,
    "$items": [
        ...
    ],
    "$value": {
    }
}

Одни методы возвращают список, другие единственный элемент. Способ отдачи содержимого отличается.

count - количество элементов в ответе. Всегда 1 для методов, возвращающих единственный результат. $items - массив с элементами ответа, если метод возвращает список. $count содержит длину массива $value - ответ для методов, возвращающих единственный результат

Формат неуспешного ответа в случае ошибки 400

Мы отдаем ошибку в обертке вида

{
    "$error": [
        "sc": 1000,
        "scn": "BODY_HAS_INVALID_FORMAT",
        "violations": [{
            "propertyPath": "user.email",
            "name": "Email",
            "invalidValue": "bad_email@////\\\"
        },
        ...
        ]
    }
}

sc - числовой подкод ошибки scn - текстовый подкод ошибки violations - в случае валидационных ошибок содержит массив несработавших валидационных правил

propertyPath - имя поля в запросе, содержащего ошибочное значение name - имя валидационного правила invalidValue - значение поля

Подкоды ошибок в случае 400 ошибки

При написании клиента можно полагаться как на текстовое, так и на числовое представление подкода ошибки.

Table 2. Ниже перечислены все используемые подкоды
Числовой подкод Текстовый подкод Почему произошло? Что делать?

1000

BODY_HAS_INVALID_FORMAT

Тело запроса передано не в JSON либо содержит ошибки формата. Эту ошибку кидает JSON-парсер на сервере

Проверить тело запроса в любом JSON-валидаторе, исправить ошибки

1001

BODY_VALIDATION_ERROR

Тело запроса не прошло валидацию на правила

Проанализировать массив violations, исправить

1002

RESOURCE_ID_IS_ABSENT

Для REST-запросов, адресованных к ресурсу по ID, не передан идентификатор ресурса

Обратить внимание на URL запроса, свериться с документацией, исправить

1003

UNIQUE_CONSTRAINT_FAILED

Для POST-запросов обозначает, что ресурс не может быть создан поскольку нарушается ограничение уникальности. Такое бывает, когда например создается уже занятый аккаунт.

Выбрать другой идентификатор ресурса для создания

Могут встречаться и другие подкоды ошибок, анализировать их не требуется. Интерпретировать как неуспешный запрос.

Отладочный идентификатор запроса

Мы нумеруем каждый вызов API, чтобы потом было проще производить "разбор полетов". Настоятельно рекомендуем логировать возвращенный идентификатор запроса. Это действительно упрощает исследование проблем при интеграции, в том числе постфактум.

HTTP/1.1 400 Bad Request
Date: Thu, 31 Mar 2016 13:38:04 GMT
Content-Type: application/json
Content-Length: 5027
x-correlation-id: xwRmpAOk
cache-control: no-cache
expires: 0
pragma: no-cache

Заголовок x-correlation-id содержит идентификатор конкретного запроса. По этому идентификатору мы легко найдем логи и поймем, что произошло. Запишите идентификатор в свои логи тоже.

Идентификатор не является глобально уникальным, текущий формат идентификатора выбран как компромисс между читаемостью и повторяемостью. По опыту эксплуатации в течении недели идентификаторы не повторяются.

Авторизация

Каждый запрос, кроме перечисленных в разделе Методы API, предназначенные для использования из браузера посетителя сайта, должен содержать API Token, переданный в формате

Authorization: Bearer {INSERT_YOUR_API_TOKEN_HERE_WITHOUT_BRACES}

Пример

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

API Token живет ограниченное время, в настоящее время мы выдаем токены на 1 год. После окончания времени действия токен перестанет работать, а сервер будет отвечать с кодом 401. Не забывайте запрашивать новый токен заранее до истечения времени жизни.

API Token является JWT-токеном. В него можно заглянуть, декодировав содержимое любой библиотекой для работы с JWT либо на сайте https://jwt.io

Для удобства работы с curl, сохраним токен в переменную окружения.

export auth_header=Authorization: Bearer {INSERT_YOUR_API_TOKEN_HERE_WITHOUT_BRACES}

Подготовка инструмента

Можно использовать любой клиент, позволяющий выполнять HTTP запросы. Рассмотрим некоторые из них.

curl

В настоящей документации мы будем использовать широко распространенную команду curl.

Для удобства пропишем переменную с базовым адресом API.

export base_url=https://api.textback.io/api

В разделе Авторизация мы установим еще одну переменную окружения - API Token.

Postman

Если curl вам не подходит, можете проходить примеры при помощи Postman.

Кстати Postman может удобно импортировать коллекцию на основе нашего машинного описания API. Импортируйте коллекцию по ссылке

API Console

Так же вы можете выполнять все примеры из браузера используя API Console.

Перед началом работы авторизуйтесь указав токен в верхнем правом углу страницы.

Токен необходимо указывать в формате Bearer {INSERT_YOUR_API_TOKEN_HERE_WITHOUT_BRACES}

Генерация клиентов для различных языков

Поскольку описание TextBack API доступно в машинном виде Swagger, вы можете воспользоваться генератором клиентов. Импортируйте описание API по ссылке и выберите меню Generate Client.

TextBack не оказывает техподдержку клиентов, сгенерированных таким образом. Область нашей ответственности - REST API. Мы вынуждены ограничить область техподдержки, поскольку не имеем возможности покрыть тестированием все типы клиентов, которые генерирует Swagger Editor.

Требования к клиенту

  1. Клиент должен игнорировать поля в ответе, неизвестные ему

  2. Клиент должен игнорировать поля, установленные в null для необязательных полей

  3. Клиент должен игнорировать отсутствие необязательного поля. Отсутствие поля приравнивается к значению null либо к пустому массиву

  4. Даты передаются как число миллисекунд прошедших с полночи 1 января 1970 UTC+0 (unixtime, но в миллисекундах)

  5. Клиент должен иметь включенную проверку валидности https-сертификата и соответствию домену

  6. Наши сервера настроены на максимальное время ожидания обработки - 10 секунд. Желательно настроить таймаут на клиенте немного больше.

Методы API, предназначенные для использования с сервера

Полный справочник методов доступен в API Console, используйте его в качестве reference documentation.

Работа с каналами

Получение списка каналов(version 1.0.0)

Метод нужен для получения идентификатов каналов, зарегистрированных для аккаунта TextBack, без знания которых невозможно отправить сообщение. В зависимости от версии api схема ответа может отличаться.

Выполним запрос

curl -v ${base_url}/channels?v=1.0.0 -H "${auth_header}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$error":null,"$items":[{"accountId":"1","channelId":1,"channel":"tg","id":"tg_1","botUsername":"TextBackSupportBot","botName":null,"botDescription":null,"botAboutText":null,"botUserPicUrl":null},{"accountId":"1","channelId":2,"channel":"tg","id":"tg_2","botUsername":"tb_prod_bot","botName":null,"botDescription":null,"botAboutText":null,"botUserPicUrl":null}],"$value":null,"$count":2}

Код ответа 200 сигнализирует, что метод выполнен успешно.

В теле ответа поле $count имеет значение 2, значит в $items массив длиной в 2 элемента. Элементы - типа Channel.

Рассмотрим тело ответа

{
  <1> "tg": [
                {
  <2>               "channel": {
                        "accountId": "1",
                        "channelId": 10,
                        "channel": "tg",
                        "id": "tg_10",
                        "tbUserId": null,
                        "botUserName": "tb_bot_2",
                        "botUsername": "tb_bot_2",
                        "webUrl": null,
                        "title": "tb_bot_2"
                    },
  <3>              "freeTextCapability": {
  <4>                   "textRestrictions": {
                           "maxSize": 600
                        },
                        "photoRestrictions": null,
                        "audioRestrictions": null,
                        "videoRestrictions": null,
                        "buttonsRestrictions": null,
                        "filesRestrictions": null,
                        "statusRestrictions": null,
                        "locationSupported": false,
                        "configurablePushBehavior": false,
                        "maxAttachmentsPerMessage": 0,
                        "messageSendIntervalMs": 1000,
                        "shouldWrapIntoCompositeIfButtonsPresent": false,
                        "channelTypeName": null,
                        "isTemplate": false,
                        "canCombineDifferentTypes": false,
                        "template": false
                    },
  <5>               "templateCapability": null
                }
            ],
  <6>  "capability": {
                   "textRestrictions": {
                       "maxSize": 600
                   },
                   "photoRestrictions": null,
                   "audioRestrictions": null,
                   "videoRestrictions": null,
                   "buttonsRestrictions": null,
                   "filesRestrictions": null,
                   "statusRestrictions": null,
                   "locationSupported": false,
                   "configurablePushBehavior": false,
                   "maxAttachmentsPerMessage": 0,
                   "messageSendIntervalMs": 40,
                   "shouldWrapIntoCompositeIfButtonsPresent": false,
                   "channelTypeName": null,
                   "isTemplate": false,
                   "canCombineDifferentTypes": false,
                   "template": false
               }
}
1 Название канала (tg, whatapp, vk, viber …​). В качестве значения - массив доступных каналов по данному названию
2 Объект содержащий представление конкретного канала
3 Объект содержащий ограничения по данному каналу. Эти данные могут быть использованы для определения совместимости канала, например, при решении орисовывать ли кнопку отправки файла.
4 Некое ограничение на текстовый ввод в канале. Например содержит maxSize для установки максимального вводимого числа знаков. Если равно null то текстовый ввод не поддерживается по данному каналу. По аналогии photoResrtictions, videoRestrictions …​
5 Поле подлежит описанию в будущем
6 Поле содержащую минимальную совместимость со всеми доступными каналами пользователя.
Некоторые поля, например, photoRestrictions содержат mimeMask поле обозначающее список поддерживаемых форматов каналом. Например, если это поле содержит "png;jpg" то канал поддерживает только изображения в формате .jpg и .png Если поле содержит "*;!exe" , то это значит канал поддерживает все форматы файлов кроме exe.
если вы сохраняете каналы в свою информационную систему, используйте или составной ключ на channelId и channel или простой ключ на id. Не следует разбирать формат id - его надо обрабатывать как прозрачную строку.

Получение списка каналов (версия 0.1.0)

Метод нужен для получения идентификатов каналов, зарегистрированных для аккаунта TextBack, без знания которых невозможно отправить сообщение. В зависимости от версии api схема ответа может отличаться.

Выполним запрос

curl -v ${base_url}/channels -H "${auth_header}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$error":null,"$items":[{"accountId":"1","channelId":1,"channel":"tg","id":"tg_1","botUsername":"TextBackSupportBot","botName":null,"botDescription":null,"botAboutText":null,"botUserPicUrl":null},{"accountId":"1","channelId":2,"channel":"tg","id":"tg_2","botUsername":"tb_prod_bot","botName":null,"botDescription":null,"botAboutText":null,"botUserPicUrl":null}],"$value":null,"$count":2}

Код ответа 200 сигнализирует, что метод выполнен успешно.

В теле ответа поле $count имеет значение 2, значит в $items массив длиной в 2 элемента. Элементы - типа Channel.

Рассмотрим тело ответа

[
  {
    "channelId": 1, (1)
    "channel": "tg", (2)
    "id": "tg_1", (3)
    "botUsername": "TextBackSupportBot", (4)
    "accountId": "1", (5)
  },
  {
    "accountId": "1",
    "channelId": 2,
    "channel": "sms",
    "id": "sms_2",
    "phone": "+79000000000", (6)
  }
]
1 Идентификатор канала
2 Тип канала, в данном случае Telegram.
3 Уникальный идентификатор ресурса (нужен только для модифицирующих REST-запросов)
4 Юзернейм бота
5 Идентификатор вашего аккаунта в TextBack
6 Номер телефона для отправки SMS
если вы сохраняете каналы в свою информационную систему, используйте или составной ключ на channelId и channel или простой ключ на id. Не следует разбирать формат id - его надо обрабатывать как прозрачную строку.

Работа с чатами и сообщениями

Получение списка диалогов

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

Выполним запрос

curl -v ${base_url}/v1/chats?from=1519882045000 -H "${auth_header}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$items":[...],"$count":10, "$nextPage":"https://api.textback.io/api/v1/chats?from=1519882045000&$skip=10"}

Код ответа 200 сигнализирует, что метод выполнен успешно.

В теле ответа поле $count имеет значение 10, значит в $items массив длиной в 10 элемента. Элементы - типа Chat.

$nextPage - ссылка на следующую страницу с автоматически подставленным пропуском чатов ($skip). Ссылка генерируется, если в ответе есть хотя бы 1 чат, независимо от того, есть ли данные на следующей странице.

Разберем пример информации о диалоге.

{
  "chatId": "103928298", (1)
  "channel": "tg", (2)
  "channelId": 2, (3)
  "id": "tg_2_103928298", (4)
  "accountId": "1", (5)
  "remoteUsername": "ivan2", (6)
  "remoteAddress": "1001001", (7)
  "remoteFirstName": "Ivan", (8)
  "remoteLastName": "Ivanov", (9)
  "lastMessage": { (10)

  },
  "userPicUrl": null, (11)
  "unreadCount": 0 (12)
}
1 Идентификатор диалога. Уникален в пределах канала
2 Тип канала
3 Идентификатор канала
4 Уникальный идентификатор ресурса (нужен только для модицифирующих REST-запросов)
5 Идентификатор вашего аккаунта в TextBack
6 Идентификатор учетной записи удаленного пользователя (с кем происходит диалог). Формат и содержание зависит от типа канала.
7 Адрес удаленного пользователя (с кем происходит диалог). Формат и содержание зависит от типа канала. Часто является идентификатором анкеты пользователя в удаленной системе.
8 Имя удаленного пользователя
9 Фамилия удаленного пользователя
10 Последнее сообщение в диалоге. Тип TbUniMessage. Рассмотрено подробно далее.
11 Ссылка на аватар удаленного пользователя
12 Количество непрочитанных сообщений оператором
если вы сохраняете диалоги в свою информационную систему, используйте или составной ключ на chatId, channelId и channel или простой ключ на id. Не следует разбирать формат id - его надо обрабатывать как прозрачную строку.
Параметр from - это дата последнего сообщения в чате (входящего или исходящего), unixtime в мс (UTC+0). Метод вернет чаты с последним сообщением не ранее этого времени. Следует использовать глубину не более 3 месяцев.
Отправка сообщения

Для отправки сообщения нам понадобится идентификатор канала и идентификатор диалога. Чтобы их получить используйте методы их предыдущих разделов.

Для отправки текстового сообщения сформируйте POST запрос с полем text.

curl -v ${base_url}/messages -H "${auth_header}" -X POST -d "{\"channel\":\"tg\",\"channelId\":2,\"chatId\":\"103928298\",\"text\":\"Привет!\"}

В полях channel, channelId и chatId значения аналогичных полей, полученных ранее из списка диалогов.

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$value":{...},"$count":1}

Код ответа 200 сигнализирует, что метод выполнен успешно.

Код ответа 200 означает, что сообщение поставлено в очередь. Он в настоящий момент не гарантирует, что сообщение доставлено, а тем более прочитано удаленным пользователем.

В теле ответа поле $count имеет значение 1, значит в $value ответ. Метод возвращает отправленное сообщение, но с заполненными некоторыми полями. Главное поле, которое может быть интересным - уникальный идентификатор сообщения.

Разберем пример ответа.

{
  "accountId": "1",
  "direction": "outbound",
  "channelId": 2,
  "channel": "tg",
  "text": "hi",
  "chatId": "103928298",
  "id": "2c12b7e7-cd40-4a9a-b828-5fd6ec6dcc72", (1)
  "sentTimestamp": 1459439095483 (2)
}
1 Уникальный идентификатор сообщения. Обязательно запишите его в БД вашей информационной системы. По идентификатору доступен трекинг статусов в дальнейшем
2 Время отправки по часам сервера Остальные поля имеют те же значения, которые мы передали, и не составляют интереса
Файлы в сообщении

В сообщение можно добавить до 10 файлов разных типов. Для отправки используется ссылка на файл, загруженный в наше облако. В каналах whatsapp и whatsappb допустимо использование публичных ссылок.
Допустимые форматы и размер файлов различаются между мессенджерами.

  1. Загружаем файл в облако
    POST https://api.textback.io/api/upload
    Файл загружается через multipart/form-data

После успешной загрузки вы получите ссылки на загруженный файл:

{
    "$value": {
        "accountId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e",
        "bucket": "cdn",
        "cloudUri": "https://f-dev.textback.io/cdn/JZ2Ckc9b_Q0/file_example_PNG_3MB.png", (1)
        "publicUri": "https://f-dev.textback.io/cdn/JZ2Ckc9b_Q0/file_example_PNG_3MB.png"
    },
    "$count": 1
}
1 Ссылка на файл в облаке. На данный момент срок хранения загруженного файла неограничен.
  1. Отправляем файл
    POST https://api.textback.io/api/messages

{
    "channel": "tg",
    "channelId": 2,
    "tbChatId": "103928298",
    "text": "Сообщение с файлами",
    "attachments": [
        {
            "kind": "image", (1)
            "channelFileId": "https://f-dev.textback.io/cdn/JZ2Ckc9b_Q0/file_example_PNG_3MB.png", (2)
            "fileName": "file_example_PNG_3MB" (3)
        },
        {
            "kind": "audio",
            "channelFileId": "https://f-dev.textback.io/cdn/IskMTBZuJrE/audio_mp3.mp3",
            "fileName": "audio_mp3"
        },
        {
            "kind": "video",
            "channelFileId": "https://f-dev.textback.io/cdn/suu1LU-pD9w/video_mp4_3mb.mp4",
            "fileName": "video_mp4_3mb"
        },
        {
            "kind": "document",
            "channelFileId": "https://f-dev.textback.io/cdn/8La3yMkhnP0/PDF_sample_1MB.pdf",
            "fileName": "PDF_sample_1MB"
        }
    ]
}
1 Тип файла. Некоторые мессенджеры по разному могут отображать принятый пользователем файл. Для более user-friendly отображения файла используйте правильный kind:
  • image

  • audio

  • video

  • document

  • voice

  • sticker

2 Ссылка на файл
3 Имя файла в локальной файловой системе отправителя
Кнопки в сообщении

Используйте интерактивные кнопки в сообщениях, чтобы повысить вовлеченность клиентов и автоматизировать сегментацию базы.

В TextBack доступно 3 типа кнопок:

  1. ActionButton - кнопка быстрого ответа

  2. HyperLinkButton - кнопка-ссылка

  3. GetContactButton - запрос контакта (только Telegram)

В моделях сообщений можно встретить еще 2 типа кнопок:

  1. InvoiceButton deprecated - кнопка-товарное предложение. Мы пока не развиваем инструмент товарных предложений в мессенджерах, и работа с ними через API недоступна.

  2. PhoneButton experimental - кнопка-телефон в шаблонах WABA, используется только при описании модели отправленного шаблона, недоступна для настройки.

В одном сообщении можно отправить до 10 кнопок ActionButton и HyperLinkButton, но только 1 GetContactButton.

Для отправки кнопки передайте её в объекте отправляемого сообщения вместе с необходимыми параметрами. Набор параметров кнопки зависит от типа кнопки.
Каждая кнопка передается отдельным объектом внутри массива buttons:

{
    "channel": "tg",
    "channelId": 2,
    "chatId": "103928298",
    "text": "Сообщение с кнопками",
    "buttons": [
        {
            "type": "HyperLinkButton", (1)
            "text": "Кнопка-ссылка",(2)
            "link": "https://textback.ru/"
        },
        {
            "type": "ActionButton", (1)
            "text": "Кнопка быстрого ответа", (2)
            "payload": "12345"
        }
    ]
}
1 Тип кнопки
2 Название кнопки

Это обязательные компоненты каждой кнопки. Ниже рассмотрим специфичные параметры.

HyperLinkButton

Самая простая кнопка, не требующая специальной подготовки. При нажатии открывает сайт в браузере.

{
    "channel": "tg",
    "channelId": 2,
    "chatId": "103928298",
    "text": "Сообщение с кнопкой ссылкой",
    "buttons": [
        {
            "type": "HyperLinkButton",
            "text": "Кнопка-ссылка",
            "link": "https://textback.ru/" (1)
        }
    ]
}
1 Валидная ссылка. Обязательный параметр.
ActionButton

Кнопка быстрого ответа - состоит из действия и ответного сообщения. Эти компоненты создаются отдельно.

Запросы для работы с ActionButton

POST https://api.textback.io/api/preparedMessages - создать сообщение, которое отправится после нажатия на кнопку
POST https://api.textback.io/api/endUserNotifications/chainActions - создать действие
GET https://api.textback.io/api/endUserNotifications/chainActions - получить все созданные действия на аккаунте
GET https://api.textback.io/api/endUserNotifications/chainActions/:id - получить действие по Id
PUT https://api.textback.io/api/endUserNotifications/chainActions/:id - изменить действие по Id
PUT https://api.textback.io/api/preparedMessages/:id - изменить сообщение по Id

Пошагово создадим кнопку ActionButton для отправки в сообщении.

  1. Создадим сообщение, которое хотим отправлять после нажатия на кнопку
    POST https://api.textback.io/api/preparedMessages

{
    "text": "Вы успешно нажали на кнопку", (1)
    "ownerType": "Account", (2)
    "ownerId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e", (3)
    "name": "Сообщение для кнопки", (4)
    "attachments": [ (5)
        {
            "kind": "image",
            "channelFileId": "https://f-dev.textback.io/cdn/aQhl3LeFxMk/logo.png",
            "publicUrl": "https://f-dev.textback.io/cdn/aQhl3LeFxMk/logo.png"
        },
        {
            "kind": "document",
            "channelFileId": "https://f-dev.textback.io/cdn/x_rqyj6AG80/file-example_PDF_1MB.pdf",
            "publicUrl": "https://f-dev.textback.io/cdn/aQhl3LeFxMk/logo.png",
            "fileName": "file-example_PDF_1MB"
        }
    ],
    "buttons": [ (6)
        {
            "payload": "b9bb7777-c0d6-8d8c-9938-0181c9ab4efd",
            "text": "Новая кнопка",
            "type": "ActionButton"
        }
    ]
}
1 Текст ответного сообщения - обязательный параметр. Для некоторых мессенджеров допустимо передать пустую строку: например, в WhatsApp "пустое" сообщение не отправится. Подойдет, если для интеграции нужна именно действие кнопки, а не сообщение из неё
2 Владелец сообщения - внутри платформы встречаются разные типы в зависимости от функционала, но при использовании API передавайте общий тип Account
3 Идентификатор владельца, специфичный для типа. Для Account - ваш accountId
4 Название сообщения внутри TextBack
5 Массив вложений
6 Массив кнопок - настраиваются, как кнопки в обычном сообщении

Одним запросом можно создать только 1 сообщение, но его затем можно переиспользовать в разных кнопках.

При успешном создании сообщения вы получите его id и объект с характеристиками:

{
    "$value": {
        "id": "3a87a4ad-e396-cf80-1b37-0183452dcc85", (1)
        "accountId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e",
        "name": "Сообщение для кнопки",
        "text": "Вы успешно нажали на кнопку",
        "createdTs": "2022-09-16T07:22:52.933Z",
        "createdByTbUserId": "2c97e3af-b32c-4fee-8564-c79ad159424e",
        "lastModifiedTs": "2022-09-16T07:22:52.933Z",
        "ownerId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e",
        "ownerType": "Account",
        "attachments": [
            {
                "kind": "image",
                "channelFileId": "https://f-dev.textback.io/cdn/aQhl3LeFxMk/logo.png",
                "publicUrl": "https://f-dev.textback.io/cdn/aQhl3LeFxMk/logo.png",
                "thumbnails": []
            },
            {
                "kind": "document",
                "channelFileId": "https://f-dev.textback.io/cdn/x_rqyj6AG80/file-example_PDF_1MB.pdf",
                "fileName": "file-example_PDF_1MB",
                "publicUrl": "https://f-dev.textback.io/cdn/aQhl3LeFxMk/logo.png",
                "thumbnails": []
            }
        ],
        "buttons": [
            {
                "type": "ActionButton",
                "text": "Новая кнопка",
                "payload": "b9bb7777-c0d6-8d8c-9938-0181c9ab4efd"
            }
        ]
    },
    "$count": 1
}
1 Id созданного сообщения
  1. Создадим действие

{
    "action": "tags.assign", (1)
    "description": "Новая кнопка", (2)
    "message": {
        "id": "3a87a4ad-e396-cf80-1b37-0183452dcc85" (3)
    },
    "actionParameters": { (4)
        "tags": [
            "push_s2_pay",
            "new_reg"
        ]
    }
}
1 Совершаемое при нажатии на кнопку действие:
  • "action": "notifications.subscribe" - подписаться на уведомления

  • "action": "notifications.unsubscribe" - запретить уведомления

  • "action": "tags.assign" - добавить тег

  • "action": "tags.remove" - удалить тег

  • "action": "nothing" - без действия

2 Внутреннее описание действия
3 Id сообщения, которое отправится при нажатии на кнопку
4 Параметры действия (только для тегов) - укажите, какой тег снять или навесить. Можно передать список из нескольких тегов в массиве tags

При успешном выполнении запроса вы получите объект созданного действия c параметрами:

{
    "$value": {
        "id": "660808c1-b5ab-f919-8855-018345306d0b", (1)
        "accountId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e",
        "description": "Новая кнопка",
        "enabled": false,
        "message": {
            "id": "3a87a4ad-e396-cf80-1b37-0183452dcc85",
            "attachments": [],
            "buttons": []
        },
        "action": "tags.assign",
        "actionParameters": {
            "tags": [
                "push_s2_pay",
                "new_reg"
            ]
        }
    },
    "$count": 1
}
1 Идентификатор созданного действия
  1. Отправим сообщение с кнопкой

{
    "channel": "tg",
    "channelId": 2,
    "chatId": "103928298",
    "text": "Сообщение с кнопкой быстрого ответа",
    "buttons": [
        {
            "type": "ActionButton",
            "text": "Нажми меня",
            "payload": "660808c1-b5ab-f919-8855-018345306d0b" (1)
        }
    ]
}
1 Идентификатор кнопки TextBack. Обязательный параметр. При нажатии на кнопку мы получаем от мессенджера вебхук с этим payload и выполним настроенное действие.

Вам необязательно настраивать payload на стороне TextBack - можно подготовить действие на своей стороне, передать в payload свой собственный ключ и подписаться на вебхук EndUserActionCommand: через него мы сообщим вам, когда получим нажатие, и вы сможете сами обработать его.

GetContactButton

Кнопка запроса контакта - только для Telegram: при нажатии автоматически сгенерируется и отправится визитка пользователя с именем и номером телефона, привязанным к профилю.
В другие мессенджеры настроенный GetContactButton отправится, как ActionButton.

Подготовка кнопки аналогична ActionButton:

  1. Создаем сообщение

  2. Создаем действие с этим сообщением

  3. Отправляем сообщение с payload

На стадии отправки добавляются новые необязательные параметры:

{
    "channel": "tg",
    "channelId": 2,
    "tbChatId": "103928298",
    "text": "Сообщением с запросом контакта",
    "buttons": [
        {
            "type": "GetContactButton",
            "text": "Поделиться контактом",
            "payload": "660808c1-b5ab-f919-8855-018345306d0b", (1)
            "oneTime": "false", (2)
            "removeKeyboard": "false" (3)
        }
    ]
}
1 Идентификатор кнопки TextBack. Необязательный параметр для GetContactButton.
2 Отвечает за "сворачивание" клавиатуры в мессенджере при нажатии на кнопку. По умолчанию - true.
3 Отвечает за "удаление" клавиатуры при отправке сообщения-ответа (то есть если настроен payload). По умолчанию - true.

В отличие от других кнопок, в сообщение можно передать только 1 кнопку GetContactButton, и другие кнопки использовать в этом же сообщении нельзя.

Редактирование кнопок

После создания кнопки вы можете изменить как её действие, так и ответное сообщение. Возможны 2 сценария:

  1. Изменить кнопку до отправки - чтобы не создавать новое сообщение/новое действие;

  2. Изменить уже отправленную кнопку - при ее нажатии даже в доставленных сообщениях будет срабатывать новое действие/отправляться новое сообщение. Полезно, если нужно поменять отправлемый контент - например, после завершившейся акции.
    Нельзя изменить параметры, которые передаются в самом сообщении при отправке - type, text, link, payload и пр.

PUT https://api.textback.io/api/preparedMessages/:id
В теле передайте полный объект нового сообщения

1 :id - идентификатор сообщения

PUT https://api.textback.io/api/endUserNotifications/chainActions/:id
В теле передайте полный объект нового действия

1 :id - идентификатор действия
Прием сообщений

Для передачи входящих сообщений (от конечного пользователя в TextBack) мы используем механизм вебхуков.

Прежде всего необходимо зарегистрировать вебхук. Узнать подробнее о подключении вебхуков и их модели данных можно в нашей документации по вебхукам: как подключить вебхуки При регистрации необходимо передать URL вашей системы, которая будет принимать запросы с вебхуками. URL должен быть доступен через интернет и отдавать status code 200 при успешном запросе. Если endpoint не отдает status code 200 на запрос - вебхук отправится еще раз, и так до 5 раз.

Затем вы должны разработать скрипт, принимающий запросы от TextBack. Мы делаем POST запросы с JSON-содержимым. Формат тела зависит от типа события. Доступны события:

  • новый чат

  • входящее сообщение в существующем чате

  • исходящее сообщение в существующем чате

  • отчет о доставке/недоставке исходящего сообщения

  • отчет о прочтении (если канал поддерживает)

  • пользователь подписался на рассылки

  • назначен тег

  • снят тег

  • изменены заметки к чату

  • канал изменил состояние (whatsapp ушел в оффлайн или вернулся в онлайн)

Блокировка чата

Если вы хотите запретить пользователю писать в подключенный канал (например, вы получаете спам), чат можно добавить в черный список:

  • входящие сообщения доставляться и передаваться в вебхуках не будут;

  • исходящие сообщения будут отправляться с ошибкой.

При отправке сообщения из Личного Кабинета TextBack исходящее сообщение и ошибка отдаются в вебхуках - new_message и MessageDeliveryCommand соответственно.
При отправке сообщения через API вы получите ошибку:

{
    "$error": {
        "sc": 400,
        "scn": "INVALID_REQUEST",
        "msg": "Can't send message, because user is blocked."
    }
}

Для блокировки чата выполните запрос:

curl -v ${base_url}/chats/28911148 -H "${auth_header} -X PATCH -d "{\"blocked\": true}"
1 28911148 - tbChatId, ID чата в TextBack

При успешной блокировке вы получите ответ 202. У чата также сменится статус на "Запретил уведомления" - пользователь будет отписан от автоворонок и чат-ботов, не будет попадать в фильтр рассылок и учитываться в оплате.

Для разблокировки чата выполните запрос:

curl -v ${base_url}/chats/28911148 -H "${auth_header} -X PATCH -d "{\"blocked\": false}"
1 28911148 - tbChatId, ID чата в TextBack

При успешной блокировке вы получите ответ 202. Важно! Пользователь не будет подписан автоматически.

Чтобы получить список всех заблокированных чатов, выполните запрос на получение чатов с фильтром:

curl -v "${base_url}/chats?from=1519882045000&blocked=true" -H "${auth_header}"

В ответе вы получите список всех заблокированных чатов с датой блокировки. Фрагмент ответа:

...
{
            "id": "whatsappb_7_79999999999",
            "accountId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e",
            "chatId": "79999999999",
            "channel": "whatsappb",
            "channelId": 7,
            "remoteAddress": "tel:+79999999999",
            "remoteAddresses": [

            ],
            "address": {

            },
            "messagingStats": {

            },
            "lastMessage": {

            },
            "remoteContact": {

              },
            "unreadCount": 0,
            "tbChatId": 28911148,
            "createdTs": "2022-06-22T08:57:57.739Z",
            "importedChat": false,
            "importedChatMerged": false,
            "allMessagesImported": false,
            "blocked": true, (1)
            "blockedTs": "2022-06-22T12:32:45.423Z", (2)
            "remoteAddressNotTel": "tel:+79999999999"
        }
...
1 Cтатус блокировки: true или false
2 Дата и время блокировки (по UTC+0) - указывается, если чат сейчас заблокирован
Работа с тегами

Через API TextBack вы можете создать новый тег, добавить или удалить тег в диалоге. Полное удаление тега из системы не реализовано через API - это можно сделать через службу поддержки.

Получить список всех существующих тегов

Выполним запрос:

curl -v ${base_url}/tags -H "${auth_header}"

При успешном ответе 200 вы получите список всех созданных тегов.

Пример ответа:

{
	"$items":[
		{
			"accountId":"a18a1ece-65ef-4540-92a3-234aa3af0b2e", (1)
			"name":"sales", (2)
            "createdTs": "2022-07-28T07:36:14.751Z" (3)
		},
		{
			"accountId":"a18a1ece-65ef-4540-92a3-234aa3af0b2e",
			"name":"promo",
            "createdTs": "2022-07-28T11:57:33.926Z"
		},
		{
			"accountId":"a18a1ece-65ef-4540-92a3-234aa3af0b2e",
			"name":"Invalid_number",
            "createdTs": "2022-07-28T12:42:48.938Z"
		},
		{
			"accountId":"a18a1ece-65ef-4540-92a3-234aa3af0b2e",
			"name":"оплатил_доставку",
            "createdTs": "2022-06-08T14:32:54.435Z"
		},
		{
			"accountId":"a18a1ece-65ef-4540-92a3-234aa3af0b2e",
			"name":"abandoned",
            "createdTs": "2022-06-10T15:56:05.140Z"
		},
		{
			"accountId":"a18a1ece-65ef-4540-92a3-234aa3af0b2e",
			"name":"новый_товар",
            "createdTs": "2022-07-18T19:14:46.211Z"
		}
	],
	"$count":6
}
1 accountId - ID вашего аккаунта в TextBack
2 name - название тега
3 createdTs - дата создания тега

Получить список тегов на конкретном чате

Выполним запрос:

curl -v ${base_url}/chats/28911148/tags -H "${auth_header}"
1 28911148 - tbChatId, ID чата в TextBack

Данные чата можно получить, например, с помощью GET-запроса {base_url}/chats - Получение списка диалогов. С 29.07.2022 теги также возвращаются в объекте чата.

При успешном ответе 200 вы получите список тегов, добавленных указанному чату.

Пример ответа:

{
    "$items": [
        {
            "chatId": "whatsappb_7_79991234567", (1)
            "name": "whatsapp", (2)
            "accountId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e", (3)
            "assignedTs": "2022-07-28T09:51:23.371Z", (4)
            "reason": "operator_assigned" (5)
        },
        {
            "chatId": "whatsappb_7_79999999999",
            "name": "уже_купил",
            "accountId": "a18a1ece-65ef-4540-92a3-234aa3af0b2e",
            "assignedTs": "2022-07-28T10:08:07.698Z",
            "reason": "operator_assigned"
        }
    ],
    "$count": 2
}
1 chatId - составной адрес чата (channel_channelId_chatId)
2 name - название тега
3 accountId - ID вашего аккаунта в TextBack
4 assignedTs - дата присвоения тега чату
5 reason - источник добавления тега (user_subscribed_on_widget, user_activated_response, operator_assigned, ve_assigned)

Создать тег

Выполним запрос:

curl -v ${base_url}/tags/tagName -H "${auth_header}" -X POST
1 tagName - название тега

При успешном создании тега вы получите ответ 202 Accepted.

Добавить тег на диалог

Создавать тег перед его добавлением необязательно - он создастся автоматически.

Пример запроса:

curl -v ${base_url}/chats/28911148/tags/tagName -H "${auth_header}" -X POST
1 28911148 - tbChatId, ID чата в TextBack
2 tagName - название вашего тега

Данные чата можно получить, например, с помощью GET-запроса {base_url}/chats.

При успешном добавлении тега вы получите ответ 202 Accepted.

Снять тег с диалога

Пример запроса:

curl -v ${base_url}/chats/28911148/tags/tagName -H "${auth_header}" -X DELETE

Данные для снятия тега аналогичны данным для добавления.

При успешном снятии тега вы получите ответ 202 Accepted.

Работа с заметками

Блок "Заметки" включает в себя 3 компонента:

  1. Текст заметки - вносится оператором вручную в ЛК TextBack или через API;

  2. Контактные номера - TextBack считывает автоматически из входящего сообщения или можно задать через API;

  3. Email - TextBack считывает автоматически из входящего сообщения или можно задать через API

Получить информацию о заметках диалога

Пример запроса:

curl -v ${base_url}/chats/28911148/memo -H "${auth_header}"
1 28911148 - tbChatId, ID чата в TextBack
Вместо tbChatId можно использовать композитный адрес чата channel_channelId_chatId - например, tg_158_65830278

Данные чата можно получить, например, с помощью GET-запроса {base_url}/v1/chats - Получение списка диалогов. С 15 декабря 2022 г. заметки также возвращаются в объекте чата.

При успешном запросы вы получите объект с компонентами заметок:

{
    "$value": {
        "memo": "Тестовая заметка", (1)
        "phones": ["+79204567890","+79204567891","+79204567892"], (2)
        "emails": ["test_email@gmail.com"], (3)
        "tbUserId": "2c97e3af-b32c-4fee-8564-c79ad159424e", (4)
        "changedTs": "2021-06-24T14:36:35.452Z" (5)
    },
    "$count": 1
}
1 memo - текст заметки в диалоге
2 phones - cохраненные контактные номера
3 emails - cохраненные email
4 tbUserId - ID оператора TextBack, который изменил заметки последний раз. Если последний раз заметка менялась автоматически, то tbUserId не возвращается.
5 changedTs - timestamp последнего изменения заметок

Если одно из полей заметок (или все поля) - пустое, в ответе оно тоже будет пустым.

{
    "$value": {
        "memo": "",
        "phones": [],
        "emails": []
    },
    "$count": 1
}

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

Если по указанному адресу чат не найден - вы получите ошибку 404 с описанием:

{
    "$error": {
        "sc": 404,
        "scn": "NOT_FOUND",
        "msg": "Chat not found"
    },
    "$count": 0,
    "$totalCount": 0
}

Используйте вебхук ChatMemoChanged, чтобы получать изменения заметок в реальном времени.

Обновить заметки

Вы можете обновить как 1 поле заметки, так и несколько. +Пример запроса с обновлением текста, номера телефона и email:

curl -v ${base_url}/chats/28911148/memo -H "${auth_header}" -X POST -d "{"memo":"Текст заметки","phones":["+79204567890"],"emails":["test_email@gmail.com"]}"
1 28911148 - tbChatId, ID чата в TextBack
Вместо tbChatId можно использовать композитный адрес чата channel_channelId_chatId - например, tg_158_65830278
2 memo - текст заметки
3 phones - массив телефонных номеров
4 emails - массив электронных почт

Можно передавать несколько номеров и несколько email сразу.
Компоненты заметки, которые уже сохранены в чате, но не передаются в запросе, - не меняются.

Пример успешного ответа 200 ОК:

{
    "$value": {
        "memo": "Текст заметки",
        "phones": ["+79204567890"],
        "emails": ["test_email@gmail.com"],
        "tbUserId": "2c97e3af-b32c-4fee-8564-c79ad159424e",
        "changedTs": "2021-06-24T14:53:42.568Z"
    },
    "$count": 1
}

Если по указанному адресу чат не найден - вы получите ошибку 400 с описанием:

{
    "$error": {
        "sc": 400,
        "scn": "INVALID_REQUEST"
    },
    "$count": 0,
    "$totalCount": 0
}

Эта ошибка может сообщать и о других проблемах при обновлении заметок. Если вы уверены, что адрес чата корректный, - напишите нам в поддержку, приложив URL запроса, тело запроса и тело ответа (с заголовком x-correlation-id).

Управление виджетом чата

Получить список виджетов

Метод нужен для получения списка настроенных виджетов. Этот метод предназначен для управления виджетами, а не для отображения на страницах сайта.

Сейчас виджеты привязаны к пользователю, который их создал. Так исторически сложилось. В настоящий момент почти все пользователи TextBack используют одну административную учетную запись в своем аккаунте, так что это не должно быть проблемой. Если для вас это важное ограничение - напишите нам.

Выполним запрос

curl -v ${base_url}/widgets/by_user/@me -H "${auth_header}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$items":[...],"$count":1}

Код ответа 200 сигнализирует, что метод выполнен успешно.

В теле ответа поле $count имеет значение 1, значит в $items массив длиной в 1 элемент. Элементы - типа Widget.

Разберем пример информации о виджете.

{
      "id":"b65372f0-bbd5-443b-bc83-8f4545dc35f2", (1)
      "userId":"fdadfd3f-7d5b-44c4-b71c-c3624d154a2e",
      "accountId":"99bffda5-5bd1-49b1-b4f2-658854797c01",
      "channels":[(2)
         {
            "channel":"facebook",(3)
            "id":"323049074708312",(4)
            "slug":"TextBack",(5)
            "enabled":true(6)
         },
         {
            "channel":"instagram",
            "id":"tbdevinsta",
            "slug":null,
            "enabled":false
         },
         {
            "channel":"tg",
            "id":"3e3fb011-d023-4d7f-8a85-8cb9439b0148",
            "slug":"tb_test_bot_4",
            "enabled":false
         }
      ],
      "welcome-avatar-url":"https://www.city-n.ru/upload/2013/01/31/319497.jpg",(7)
      "welcome-name":"Вася",(8)
      "welcome-seconds":1,(9)
      "welcome-tooltip":"Приветствую!\n<br>\n<br>Дайте нам знать, если у вас возникнут вопросы.\n<br>\n<br>Просто задайте вопрос через удобный вам мессенджер.",(10)
      "disable-welcome-cursor":false,(11)
      "show-welcome":true,(12)
      "welcome-avatar":"image",(13)
      "widget-size":45,(14)
      "bg-color":"2cbd96",(15)
      "show-waterdrop":true,(16)
      "show-lightbox":true,(17)
      "widget-desktop-icon":"desktopCarousel",(18)
      "widget-mobile-icon":"mobileAngle",(19)
      "disable-desktop-tooltip-en":true,(20)
      "disable-mobile-tooltip-en":true,(21)
      "desktop-tooltiptext-en":"",(23)
      "mobile-tooltiptext-en":"Hey, guys",(24)
      "disable-desktop-tooltip-ru":false,
      "disable-mobile-tooltip-ru":false,
      "desktop-tooltiptext-ru":"Интересует?",
      "mobile-tooltiptext-ru":"Интересует?",
      "show-mobile-version":true,(25)
      "show-mobile":true,(26)
      "widget-alignment":"widget-alignment-right",(27)
      "widget-alignment-left":"",(28)
      "widget-alignment-right":"0",
      "widget-alignment-bottom":"0",
      "custom-channel-tab-number":1,
      "custom-channel-id":0,
      "custom-channel-tooltip":"Онлайн-чат",(29)
      "custom-channel-icon":"default",(30)
      "custom-channel-action":"link",(31)
      "custom-channel-icon-url":"",(32)
      "custom-channel-link":"link",(33)
      "custom-channel-callback":"",(34)
      "is-custom-wide":false,(35)
      "disable-custom-channel-mo":false,(36)
      "disable-custom-channel-tu":false,
      "disable-custom-channel-we":false,
      "disable-custom-channel-th":false,
      "disable-custom-channel-fr":false,
      "disable-custom-channel-sb":false,
      "disable-custom-channel-su":false,
      "custom-channel-from-hours":0,(37)
      "custom-channel-from-minutes":0,
      "custom-channel-to-hours":23,(38)
      "custom-channel-to-minutes":0,
      "custom-channel-tab-number1":2,(39)
      "custom-channel-id1":1,
      "custom-channel-tooltip1":"Онлайн-чат",
      "custom-channel-icon1":"default",
      "custom-channel-action1":"link",
      "custom-channel-icon-url1":"",
      "custom-channel-link1":"link",
      "custom-channel-callback1":"",
      "is-custom-wide1":false,
      "disable-custom-channel-mo1":false,
      "disable-custom-channel-tu1":false,
      "disable-custom-channel-we1":false,
      "disable-custom-channel-th1":false,
      "disable-custom-channel-fr1":false,
      "disable-custom-channel-sb1":false,
      "disable-custom-channel-su1":false,
      "custom-channel-from-hours1":0,
      "custom-channel-from-minutes1":0,
      "custom-channel-to-hours1":23,
      "custom-channel-to-minutes1":0,
      "custom-channels-total":2,(40)
      "widget-open":"open-click-mouseover",(41)
      "hide-tb-logo":""(42)
}
1 уникальный идентификатор виджета. Требуется для отрисовки (или получения настроек) в коде встраивания виджета на сайт.
2 массив из кнопок-каналов (не считая кастомных кнопок)
3 тип канала (vk|facebook|whatsapp|tg|viber|whatsappb). Требуется для определения способа и деталей отрисовки кнопки и реакции на клик
4 идентификатор канала в мессенджере. Требуется для создания ссылки начала чата. Это не TextBack идентификатор, а именно мессенджерский.
5 надпись на кнопке, как правило имя паблик аккаунта. Может отсутствовать, тогда нужно использовать идентификатор
6 флаг, включен ли канал в настройках
7 ссылка на аватар "оператора"
8 имя "оператора"
9 через сколько секунд отображать виджет в режиме приветствия
10 текст в приветствии, HTML
11 N/A
12 отображать ли виджет в режиме приветствия
13 если имеет значение image, то отображать аватар, а не иконку по умолчанию
14 размер (ширина и высота) виджета в пикселях
15 цвет виджета
16 включить Waterdrop анимацию
17 затемнять фон
18 стиль иконки на десктопе (desktopMessaging|desktopTelegram|desktopPhone|desktopBubble|desktopCarousel)
19 стиль иконки на мобильном устройстве (mobileAngle|mobileMessaging|mobileTelegram|mobilePhone|mobileBubble|mobileCarousel)

Помимо параметров отображения указанных выше вы можете хранить собственные параметры. TextBack будет их сохранять и возвращать виджету во время отображения на страницах сайта. Рекомендуется задавать префикс для пользовательских настроек, чтобы они пересекались с настройками TextBack. Разрешено хранить не более 50 пользовательских настроек, размер данных каждой настройки - 1кб.

Создать виджет

Метод нужен для создания нового инстанса виджета. Новый виджет нужен если вы хотите отображать на разных страницах сайта виджеты с разными настройками или кнопками каналов.

Разрешено создавать не более 2 виджетов на тарифе Start и 10 виджетов на тарифе PRO.

При создании виджета необходимо задать хотя бы одну кнопку канала.

При создании виджета вы можете передать собственные параметры. TextBack будет их сохранять и возвращать виджету во время отображения на страницах сайта. Рекомендуется задавать префикс для пользовательских настроек, чтобы они пересекались с настройками TextBack. Разрешено хранить не более 50 пользовательских настроек, размер данных каждой настройки - 1кб.

Если вы предполагаете использовать виджет TextBack, то необходимо передать все настройки, которые возвращаются в любом примере ответа уже созданного виджета.

Создать виджет с кнопкой канала ВКонтакте и без дополнительных настроек

Выполним запрос

curl -v ${base_url}/widgets -H "${auth_header}" -X POST --data "{\"channels\":[{\"channel\":\"vk\",\"id\":\"123\"}]}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$value":
    {
        "id":"df2002ba-c78e-4a65-aa5a-7553bdc061a5",(1)
        "channels":[(2)
            {
                "channel":"vk",(3)
                "id":"123",(4)
                "slug":null,(5)
                "enabled":true(6)
            }
        ]
    }
}
1 уникальный идентификатор созданного виджета. Требуется для отрисовки (или получения настроек) в коде встраивания виджета на сайт.
2 массив из кнопок-каналов (не считая кастомных кнопок)
3 тип канала (vk|facebook|whatsapp|tg|viber|whatsappb). Требуется для определения способа и деталей отрисовки кнопки и реакции на клик
4 идентификатор канала в мессенджере. Требуется для создания ссылки начала чата. Это не TextBack идентификатор, а именно мессенджерский.
5 надпись на кнопке, как правило имя паблик аккаунта. Может отсутствовать, тогда нужно использовать идентификатор
6 флаг, включен ли канал в настройках

Код ответа 200 сигнализирует, что метод выполнен успешно. В $value объект типа Widget.

Создать виджет с кнопкой канала Facebook и дополнительными настройками

Выполним запрос

curl -v ${base_url}/widgets -H "${auth_header}" -X POST --data "{\"channels\":[{\"channel\":\"facebook\",\"id\":\"123\"}],\"x-my-color\":\"#112233\"}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$value":
    {
        "id":"c6d15f3a-d354-46cc-a4bd-757f477afc12",(1)
        "channels":[(2)
            {
                "channel":"facebook",(3)
                "id":"123",(4)
                "slug":null,(5)
                "enabled":true(6)
            }
        ],
        "x-my-color":"#112233"(7)
    }
}
1 уникальный идентификатор созданного виджета. Требуется для отрисовки (или получения настроек) в коде встраивания виджета на сайт.
2 массив из кнопок-каналов (не считая кастомных кнопок)
3 тип канала (vk|facebook|whatsapp|tg|viber|whatsappb). Требуется для определения способа и деталей отрисовки кнопки и реакции на клик
4 идентификатор канала в мессенджере. Требуется для создания ссылки начала чата. Это не TextBack идентификатор, а именно мессенджерский.
5 надпись на кнопке, как правило имя паблик аккаунта. Может отсутствовать, тогда нужно использовать идентификатор
6 флаг, включен ли канал в настройках
7 пользовательская настройка с именем x-my-color. Имя выбрано произвольно. TextBack сохранил настройку и вернул в ответе.

Код ответа 200 сигнализирует, что метод выполнен успешно. В $value объект типа Widget.

Сохранить настройки виджета

Метод сохранения настроек работает так же, как и создания, но метод - PUT, а в URL задается идентификатор изменяемого виджета.

Метод производит полную замену настроек, то есть это не частичное изменение только переданных полей. Если какие-то поля не будут переданы в метод сохранения настроек - они удалятся.

При помощи этого метода изменяются как пользовательские настройки, так и каналы: добавляются новые, удаляются старые. Просто передайте нужный список каналов в массиве channels и он будет полностью заменен.

Выполним запрос

curl -v ${base_url}/widgets/c6d15f3a-d354-46cc-a4bd-757f477afc12 -H "${auth_header}" -X PUT --data "{\"channels\":[{\"channel\":\"facebook\",\"id\":\"123\"}],\"x-my-color\":\"#332211\"}"

Пример ответа

< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 384
< x-correlation-id: 2J972JPQ
< cache-control: no-cache
< expires: 0
< pragma: no-cache
<
{"$value":
    {
        "id":"c6d15f3a-d354-46cc-a4bd-757f477afc12",(1)
        "channels":[(2)
            {
                "channel":"facebook",(3)
                "id":"123",(4)
                "slug":null,(5)
                "enabled":true(6)
            }
        ],
        "x-my-color":"#112233"(7)
    }
}
1 уникальный идентификатор измененного виджета. Требуется для отрисовки (или получения настроек) в коде встраивания виджета на сайт.
2 массив из кнопок-каналов (не считая кастомных кнопок)
3 тип канала (vk|facebook|whatsapp|tg|viber|whatsappb). Требуется для определения способа и деталей отрисовки кнопки и реакции на клик
4 идентификатор канала в мессенджере. Требуется для создания ссылки начала чата. Это не TextBack идентификатор, а именно мессенджерский.
5 надпись на кнопке, как правило имя паблик аккаунта. Может отсутствовать, тогда нужно использовать идентификатор
6 флаг, включен ли канал в настройках
7 пользовательская настройка с именем x-my-color. Видим, что возвращено измененное значение свойства.

Код ответа 200 сигнализирует, что метод выполнен успешно. В $value объект типа Widget с измененными данными.

Методы API, предназначенные для отправки рассылки

Раздел находится на обновлении.

Методы API, предназначенные для использования из браузера посетителя сайта

Документация доступна по данному адресу: https://www.npmjs.com/package/@textback/notification-widget

Остальные методы

Документация по остальным методам (а так же и по перечисленным здесь) доступна в API Console