Офіційний партнер Viber в Україні

FAQ API Direct Hub

Відповіді для розробників інтеграцій: відправлення та статуси повідомлень, ідемпотентність, сесії Viber, вебхуки, розсилки та оплата.

Нічого не знайденоСпробуйте інше формулювання або коротший запит.

Відправлення та статуси

Що означає HTTP 200 у відповіді на відправку?

HTTP 200 означає, що Direct Hub прийняв повідомлення. У відповіді приходить { id, status }, де status = WaitingToSend.

  • HTTP 200 ніколи не містить відмови у відправленні. Відмова Viber приходить пізніше, вебхуком MessageSendError.
  • Помилка не може повернутися з HTTP 200.
  • Помилки, виявлені до прийняття повідомлення, повертаються кодами 4xx/5xx у форматі application/problem+json з полями title, status, detail, traceId (див. HTTP-помилки під час відправлення).
Які події приходять після відправлення повідомлення?

Кожному етапу відповідає таке:

ЕтапЩо надходить від Direct Hub
Прийнято Direct HubHTTP 200, { id, status }, status = WaitingToSend
Відправлено / прийнято Viberвебхук MessageSent
Доставленовебхук MessageDelivered
Прочитановебхук SeenMessage
Помилкавебхук MessageSendError, причина в полі error
Строк доставки минуввебхук MessageExpired
Які події за повідомленням є остаточними?

Статус у відповіді на відправлення — WaitingToSend. Далі приходять події:

ПодіяОстаточна
MessageSentні
MessageDeliveredуспіх. SeenMessage може прийти пізніше
SeenMessageтак
MessageSendErrorтак, помилка
MessageExpiredтак, не доставлено
Коли можна показувати повідомлення як доставлене?
  • До події MessageDelivered повідомлення не слід показувати як доставлене.
  • MessageDelivered може прийти кілька разів, якщо в отримувача Viber встановлено на кількох пристроях.
Який строк доставки повідомлення?

Строк доставки — 10 хвилин. Повідомлення, не доставлене за цей час, отримує MessageExpired.

Які значення може мати поле error у MessageSendError?
  • коди Viber — BadRecipient, RecipientNotRegistered, RecipientBlockedMessages, DoesNotSupportDevice, AttemptExceededSession, BadParameters та інші;
  • мережеві збої під час передавання у Viber — Network error has occurred., Timeout has occurred., Unsuccessful status code..
Які HTTP-помилки можливі під час відправлення і чи варто повторювати запит?
КодЗначенняПовторювати?
400помилка валідації, немає активної сесії, сесію призупиненоні, потрібно виправити запит або умову
402недостатньо коштів або вичерпано пакетні, до поповнення або нового періоду
403компанію заблоковано або не призначено тарифні
404ресурс не знайденоні
409запит із цим idempotencyKey ще виконуєтьсятак, через кілька секунд із тим самим ключем
422idempotencyKey уже використано для іншого отримувачані, потрібен новий ключ
429перевищено ліміт запитівтак, після Retry-After
503ресурс тимчасово зайнятийтак, із тим самим idempotencyKey
500внутрішня помилкаповторіть пізніше; якщо помилка повторюється — зверніться до підтримки
Які помилки Viber має сенс повторювати?
  • відмови за отримувачем (немає Viber, блокування, неправильний номер) повторювати безглуздо;
  • після мережевого збою під час передавання у Viber повідомлення могло все ж піти, тому повтор із новим ключем може дати дубль.
Чи можна отримати статус повідомлення або історію через API?

Наразі API не дає змоги:

  • отримати статус за messageId;
  • знайти повідомлення за trackingData;
  • вивантажити історію за період;
  • отримати список поточних сесій і підписок.

Стан потрібно накопичувати у себе за вебхуками. Події, пропущені під час недоступності вашого сервера, повторно не доставляються (див. доставку вебхуків).

Дізнатися поточний статус конкретного повідомлення можна одним способом: повторити запит на відправлення з тим самим idempotencyKey (див. Ідемпотентність і повтори). Нове повідомлення при цьому не створюється.

Ідемпотентність і повтори

Як працює idempotencyKey?
  • Ключ обов'язковий для всіх ендпоінтів відправлення. Без ключа або з порожнім GUID запит відхиляється з кодом 400.
  • Ключ унікальний у межах бізнес-номера, до якого прив'язано API-токен, і зберігається стільки ж, скільки саме повідомлення.
Що повертає повторний запит із тим самим ключем?

Повторний запит із тим самим ключем повертає HTTP 200 з тим самим id і поточним status першого повідомлення, а також заголовок Idempotent-Replayed: true. Нове повідомлення не створюється, оплата повторно не списується, сесійний ліміт не витрачається.

Як визначається, що запит є повтором?

Ключ шукається серед повідомлень того самого бізнес-номера, тобто того самого API-токена. Якщо повідомлення з таким ключем знайдено, порівнюється тільки отримувач:

  • отримувач той самий — запит вважається повтором: HTTP 200, попередній id, поточний status і заголовок Idempotent-Replayed: true;
  • отримувач інший — відповідь 422 «Idempotency key already used».

Інші поля запиту (текст, шаблон і його параметри, зображення або файл, trackingData) не порівнюються. Запит із тим самим ключем і тим самим отримувачем, але з іншим текстом, поверне вже створене повідомлення, а нове не буде відправлено. Тому для кожного нового повідомлення використовуйте новий ключ.

Чи відправить повтор із тим самим ключем повідомлення заново, якщо перше завершилося помилкою?

Ні. Повтор не відправляє повідомлення заново, навіть якщо перше завершилося помилкою: ключ означає «те саме повідомлення». Щоб відправити заново, використайте новий ключ.

Що буде, якщо перший запит було відхилено?

Якщо перший запит було відхилено до створення повідомлення (коди 400, 402, 403, 503), повідомлення з цим ключем немає, і повтор із ним виконується як нова спроба.

Що буде, якщо використати той самий ключ для іншого отримувача?

Той самий ключ з іншим отримувачем відхиляється з кодом 422.

Чи безпечно надсилати одночасні запити з одним ключем? Що означає 409?

Одночасні запити з одним ключем безпечні: буде створено одне повідомлення.

Якщо перший запит із цим ключем ще виконується довше 2 секунд (наприклад, завантажується великий файл), повтор отримає 409. Повторіть запит через кілька секунд: прийде результат першого запиту із заголовком Idempotent-Replayed: true.

Як правильно генерувати ключі та повторювати запити?

Генеруйте новий ключ для кожного нового повідомлення і повторюйте запит із тим самим ключем, якщо відповідь не отримано (таймаут, обрив з'єднання) або отримано 503.

Рекомендовані інтервали повторів — див. З якими інтервалами повторювати запити?, а дії для кожного коду — у таблиці HTTP-помилок.

Отримувачі

У якому форматі передавати номер отримувача?

+380XXXXXXXXX, із плюсом. Наразі підтримуються лише номери України.

У якому форматі приходить номер у вхідних повідомленнях?

У тому вигляді, в якому його передає Viber, із плюсом.

Чи можна заздалегідь перевірити, чи є в отримувача Viber?

Ні, такої попередньої перевірки немає.

Як розрізнити проблеми з номером або отримувачем?
  • неправильний формат номера — одразу відповідь 400;
  • номер некоректний за даними Viber — MessageSendError, error = "BadRecipient";
  • в отримувача немає Viber — "RecipientNotRegistered";
  • отримувач заблокував бізнес-акаунт — "RecipientBlockedMessages";
  • пристрій не підтримує такий тип повідомлення — "DoesNotSupportDevice".

Ліміти запитів і розміри файлів

Які ліміти запитів?

Ліміти діють на IP-адресу клієнта: для IPv4 — на конкретну адресу, для IPv6 — на підмережу /64. Методи поділено на групи, і в кожної групи свій лічильник:

ГрупаЛіміт
Відправлення повідомлень (/api/message/...)1200 запитів на хвилину
Решта методів API300 запитів на хвилину
  • Рахунок ведеться у фіксованому вікні: воно починається з першого запиту і триває хвилину. Сплеск усередині вікна допустимий, доки не вичерпано ліміт.
  • Окремого обмеження на кількість паралельних запитів немає.
Що відбувається в разі перевищення ліміту?

Одразу повертається HTTP 429 із заголовком Retry-After (через скільки секунд відкриється нове вікно). Запит не виконується і не тарифікується.

З якими інтервалами повторювати запити?
  • після 429 — чекати стільки секунд, скільки вказано в Retry-After;
  • після 503 і мережевих помилок — експоненційна затримка, наприклад 1, 2, 4, 8 секунд, із тим самим idempotencyKey.
Як робити масові відправлення, не витрачаючи ліміт запитів?

Використовуйте розсилки: вони не витрачають ліміт на відправлення повідомлень.

Які обмеження на текст, файли та зображення? Чи діють обмеження Bot API?

Обмеження Bot API до Direct Hub не застосовуються. Діють такі:

ПараметрОбмеження
Текст повідомленнядо 1000 символів
trackingDataвід 3 до 256 символів
Файл (сесійне відправлення)до 99 МБ, назва файлу разом із розширенням — до 25 символів
Зображеннядо 50 МБ
Підпис до сесійного зображенняне підтримується: сесійне зображення відправляється без тексту
Текст кнопки промоповідомленнядо 30 символів

Сесії Viber

Що відкриває сесію? Чи відкриває її відповідь на розсилку?

Так. Сесію відкриває будь-яке вхідне повідомлення від користувача, зокрема відповідь на розсилку.

Чи продовжує нове вхідне повідомлення сесію?

Ні. Вікно фіксоване: 24 години від першого вхідного. Нове вхідне не продовжує його і не скидає ліміт у 60, але знімає паузу після 10 вихідних поспіль без відповіді.

Що входить у ліміт 60 повідомлень сесії?

Сесійні відправлення (текст, зображення, файл), прийняті Direct Hub. Місце в ліміті витрачається в момент прийняття і не повертається, навіть якщо Viber потім відмовить. Платні повідомлення та повтори з тим самим idempotencyKey у ліміт не входять.

Як дізнатися, скільки повідомлень залишилося в сесії?

API для цього немає. Залишок рахується так: 60 мінус кількість прийнятих сесійних відправлень з моменту події SessionOpened.

Коли закривається сесія і які бувають причини закриття?
  • За часом: сесія закривається через 24 години після відкриття. Подія SessionClosed (Expired) може прийти із затримкою до кількох хвилин, але відправлення в сесію, що минула, відхиляється одразу.
  • За кількістю: сесія закривається одразу на 60-му повідомленні, приходить SessionClosed (MessageLimitReached).

Причини закриття сесії (closeReason):

  • Expired — минули 24 години;
  • MessageLimitReached — вичерпано ліміт у 60 повідомлень;
  • ViberRejected — Viber повідомив, що сесію на його боці вже закрито.
Що буде з одночасними відправленнями на межі ліміту сесії?

Проходять рівно 60. Решта отримують 400 або йдуть платно, якщо ввімкнено автоперехід (див. автоматичний перехід до платного відправлення).

Що буде, якщо сесія минула, поки повідомлення в черзі?

Viber може відхилити повідомлення. Тоді прийдуть MessageSendError (AttemptExceededSession) і SessionClosed (ViberRejected). Відхилене повідомлення не тарифікується.

Чи є перехід до платного відправлення для зображень і файлів?

Для зображень є. /api/message/session/image приймає той самий прапорець fallbackToPromotional, і на нього так само діє налаштування номера. Без сесії зображення йде платним промоповідомленням «лише зображення» за тарифом цього типу.

Для файлів немає: у Viber немає промоповідомлення з файлом. Без сесії /api/message/session/file повертає 400 незалежно від налаштування номера.

Вхідні повідомлення та вебхуки

Як отримувати події від Direct Hub?

Вебхук — єдиний механізм отримання подій.

Як доставляються вебхуки? Чи є повторні спроби?

Direct Hub чекає на відповідь 2xx 10 секунд і робить одну спробу без повторів. Події, пропущені під час недоступності вашого сервера, повторно не доставляються.

Як перевірити підпис вебхука?

Кожен вебхук — це POST із JSON-тілом і двома заголовками:

ЗаголовокЗначення
X-Webhook-Signaturesha256= і далі HMAC-SHA256 від тіла запиту у hex, нижній регістр
X-Webhook-Eventтип події, збігається з полем eventType у тілі

Як перевірити:

  1. Візьміть тіло запиту як є, у байтах, до розбору JSON.
  2. Декодуйте секрет вебхука з hex: 64 hex-символи дають 32 байти. Ці байти і є ключем HMAC.
  3. Обчисліть HMAC-SHA256 від тіла цим ключем, переведіть результат у hex у нижньому регістрі й додайте префікс sha256=.
  4. Порівняйте результат із заголовком X-Webhook-Signature функцією порівняння за сталий час. Якщо значення не збігаються, відхиліть запит і не обробляйте подію.

Найчастіша помилка — використати як ключ сам рядок секрету. Ключ HMAC — це байти, отримані декодуванням hex-секрету. З рядком як ключем підпис не збігатиметься ніколи.

Інші причини розбіжності:

  • підпис рахують від JSON, який повторно серіалізували після розбору: порядок полів, пробіли або екранування змінюються, і підпис уже не збігається. Підпис рахується тільки від сирого тіла;
  • ваш фреймворк або проксі змінив тіло до вашого коду (перекодування, обрізання пробілів).

Node.js

const crypto = require('crypto');

// rawBody — Buffer із сирим тілом запиту (наприклад, express.raw({ type: 'application/json' }))
function verifyWebhook(rawBody, signatureHeader, secretHex) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', Buffer.from(secretHex, 'hex'))
    .update(rawBody)
    .digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Python

import hashlib
import hmac

def verify_webhook(raw_body: bytes, signature_header: str, secret_hex: str) -> bool:
    expected = "sha256=" + hmac.new(bytes.fromhex(secret_hex), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

C#

using System.Security.Cryptography;
using System.Text;

static bool VerifyWebhook(byte[] rawBody, string? signatureHeader, string secretHex)
{
    var hash = HMACSHA256.HashData(Convert.FromHexString(secretHex), rawBody);
    var expected = "sha256=" + Convert.ToHexString(hash).ToLowerInvariant();
    return CryptographicOperations.FixedTimeEquals(
        Encoding.ASCII.GetBytes(expected),
        Encoding.ASCII.GetBytes(signatureHeader ?? ""));
}

PHP

// $rawBody = file_get_contents('php://input');
// $signatureHeader = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
function verifyWebhook(string $rawBody, string $signatureHeader, string $secretHex): bool
{
    $expected = 'sha256=' . hash_hmac('sha256', $rawBody, hex2bin($secretHex));
    return hash_equals($expected, $signatureHeader);
}
Де взяти секрет для перевірки підпису? Що робити, якщо його втрачено?
  • Секрет генерується під час реєстрації вебхука і повертається один раз, у полі secret відповіді на створення. Це рядок із 64 hex-символів (32 випадкові байти).
  • Повторно отримати секрет не можна: у списку вебхуків і в інших відповідях його немає. Збережіть секрет одразу після створення.
  • Секрет не змінюється, коли ви змінюєте URL або типи подій вебхука.
  • Якщо секрет втрачено або скомпрометовано, видаліть вебхук і зареєструйте новий. Новий вебхук отримає новий секрет.

Як перевіряти підпис — див. Як перевірити підпис вебхука?

Як отримати фото, відео чи файл, які надіслав користувач?

Користувач може надіслати фото, відео або файл. У вебхуку NewMessage приходять поля fileUrl і fileName. Посилання веде на сервер Viber. За документацією Viber файл зберігається до 7 днів, після цього недоступний, і відновити його не можна.

Рекомендуємо завантажувати файл одразу після отримання події.

Розсилки

Скільки отримувачів може бути в розсилці? Чи є персоналізація?

До 200 000 отримувачів. Використовуються лише схвалені промошаблони. Параметри шаблону задаються один раз на всю розсилку, персоналізації за отримувачем немає.

Чи можна передати власні ідентифікатори для розсилки?

Ні. Розсилка отримує id Direct Hub.

Що буде, якщо повторити операції з розсилкою?
  • створення розсилки не ідемпотентне: повтор створить ще одну розсилку;
  • додавати отримувачів можна повторно: дублікати номерів відкидаються, у відповіді є added і skippedDuplicates;
  • повторний запуск уже запущеної розсилки поверне 400, другого списання не буде.
Чи можна запланувати, призупинити або скасувати розсилку?

Ні, планування, пауза та скасування не підтримуються.

Які статуси має розсилка? Чи є статуси окремих повідомлень?

У розсилки доступний лише загальний стан: Configuration, ReadyToSend, InProgress, Completed, Abandoned. Статуси окремих повідомлень і вебхуки доставки для розсилок не надаються.

Що означає статус Completed?

Відправлення всім отримувачам завершено. Це не означає, що всі повідомлення доставлено.

Тарифи та оплата

Коли витрачається пакет або баланс?

Під час відправлення сума резервується. Списується вона, коли Viber прийняв повідомлення (MessageSent).

Чи оплачуються повідомлення з помилкою або простроченим строком доставки?

У разі MessageSendError резерв повертається. Повідомлення з MessageExpired оплачене, бо Viber його прийняв.

Коли оновлюється пакет?

Пакет видається 1-го числа за київським часом. Невикористаний залишок минулого місяця згорає.

Що відбувається, коли пакет вичерпано?
  • на пакетному тарифі платні відправлення відхиляються з кодом 402 до наступного місяця, навіть якщо на балансі компанії є гроші;
  • на тарифі без пакета списання продовжується з балансу компанії;
  • сесійне листування безкоштовне і залишається доступним в обох випадках.
Чи є API для залишку пакета, балансу та історії списань?

Через API-токен таких методів немає. Залишок та історія операцій доступні в особистому кабінеті.

Шаблони

Що можна робити з шаблонами через API?

За API-токеном можна лише отримати список шаблонів, за бажанням із фільтром за типом. Створення шаблону та надсилання на модерацію доступні в особистому кабінеті.