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

API v2 (бета)

API v2

API v2 — новый REST API WbizTool: отдельный ключ для каждого приложения ровно с теми правами, которые ему нужны, URL в стиле ресурсов, настоящие коды состояния HTTP, подписанные вебхуки JSON и безопасные повторы запросов. На этой странице описано то, что общее для всех запросов. Каждый endpoint описан на страницах ресурсов.

Базовый URL#

https://wbiztool.com/api/v2

У путей нет завершающей косой черты (/api/v2/messages), но и с ней запрос тоже принимается. Адрес, которого не существует, возвращает 404 с кодом not_found.

Быстрый пример#

Проверьте ключ запросом GET /me. Он работает с любой областью доступа и ничего не отправляет:

curl https://wbiztool.com/api/v2/me \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"
{
  "workspace": { "id": 5012, "name": "Acme Bakery" },
  "key": {
    "id": 7,
    "name": "Order system",
    "mode": "live",
    "scopes": ["messages:send", "messages:read"],
    "limited_to_numbers": false,
    "number_ids": [],
    "expires_at": null
  },
  "plan": { "name": "Starter" },
  "limits": {
    "requests_per_minute": 60,
    "requests_per_day": 10000,
    "messages_per_number_per_day": 1000,
    "messages_remaining": null
  }
}

messages_remaining равен null, если тариф даёт безлимитные сообщения. plan равен null, если у рабочего пространства нет активного тарифа.

Ключи#

Передавайте ключ в заголовке Authorization в каждом запросе:

Authorization: Bearer wbz_live_…

client_id не нужен: ключ сам указывает на своё рабочее пространство. Ключ v2 начинается с wbz_live_ или wbz_test_, за которыми идут 38 букв и цифр. Ключи v1 не работают в v2 (они получают v1_key_on_v2), а ключи v2 не работают в v1.

Создание ключа#

Владельцы создают ключи на странице Настройки → API-ключи, в карточке API-ключи v2: нажмите Создать ключ v2 и выберите:

  • Название: приложение, которое будет им пользоваться, до 50 символов.
  • Тип ключа: Рабочий отправляет настоящие сообщения; Тестовый всё проверяет и ничего не отправляет (см. Тестовый режим).
  • Что он может делать: области доступа или Всё.
  • Какие номера он может использовать: все номера, включая добавленные позже, или только некоторые (см. Ключи только для некоторых номеров).
  • Истекает: никогда или через 30 дней, 90 дней либо 1 год.

Ключ показывается один раз. Сразу скопируйте его и сохраните на своём сервере, например в переменной окружения. WbizTool хранит только его хеш и последние четыре символа, поэтому потерянный ключ нельзя показать снова: отзовите его и создайте новый.

В рабочем пространстве может быть до 10 неотозванных ключей v2. В карточке у каждого ключа показаны последние четыре символа, области доступа, номера, срок действия, а также когда и с какого IP-адреса он использовался в последний раз. Отозвать сразу останавливает ключ, а вместе с ним и созданные им webhook endpoint. Ключ с истёкшим сроком действия получает api_key_expired.

Области доступа#

Каждый ключ может делать только то, что разрешают его области доступа (scopes). Запрос за их пределами возвращает 403 с missing_scope, а required_scope в ошибке говорит, какая область нужна.

ОбластьЧто она разрешает
messages:sendОтправлять сообщения и пакеты, отменять ожидающие сообщения: POST /messages, POST /messages/batch, DELETE /messages/{id}
messages:readЧитать сообщения и их статус (GET /messages, GET /messages/{id}) и управлять webhook endpoint
remindersСоздавать, просматривать, изменять, ставить на паузу и удалять напоминания
numbersПросматривать номера, их подключение и подключать номера WhatsApp
mediaЗагружать, просматривать и удалять файлы в Медиакаталоге
contactsПроверки номеров (endpoint для контактов появятся позже)

GET /me не требует особой области доступа. Для отправки сохранённому контакту через to.contact_id нужна только messages:send.

Ключи только для некоторых номеров#

Ключ, ограниченный некоторыми номерами, работает только с ними:

  • Он отправляет только с этих номеров и просматривает, читает и отменяет только их сообщения. Другой номер в from получает number_not_allowed.
  • GET /numbers показывает только эти номера. Ключ может переподключать их, но не может добавить новый номер.
  • Он видит и изменяет только напоминания, которые отправляются с этих номеров, а новое напоминание должно указывать один из них в from.
  • Он вообще не может управлять webhook endpoint, потому что они получают события всего рабочего пространства.

GET /me показывает limited_to_numbers и number_ids, которые ключ может использовать.

Запросы#

  • JSON на входе и на выходе. Передавайте тело как Content-Type: application/json. Единственное исключение — загрузка файла, там multipart/form-data. Каждый ответ — JSON, включая ошибки.
  • Имена полей в snake_case, а неизвестные поля отклоняются: опечатка вроде txt возвращает validation_failed, а не игнорируется.
  • Номера телефонов — в международном формате с + (E.164), например +919876543210. Пробелы и дефисы допустимы; номер без + отклоняется с invalid_phone.
  • Время — в ISO 8601 со смещением, например 2026-10-20T09:30:00+05:30 или 2026-10-20T04:00:00Z. Время без смещения отклоняется с invalid_datetime. Время в ответах указывается в UTC и заканчивается на Z, кроме next_run_at напоминания: оно в часовом поясе напоминания.
  • ID — целые числа, например id номера (from при отправке) или id сообщения.
  • Коды состояния значат то, что написано: 200 OK, 201 создано, 202 принято (в очереди), 400 запрос неверен, 401 ключ неверен, 402 закончились сообщения, 403 не разрешено, 404 не найдено, 409 конфликт, 413 слишком большой, 415 неверный тип содержимого, 422 значение нельзя использовать, 429 слишком много запросов, 5xx проблема на нашей стороне.

Ответы содержат Cache-Control: no-store.

Ошибки#

У каждой ошибки одинаковый формат:

{
  "error": {
    "code": "invalid_phone",
    "message": "This is not a valid phone number. Write it in international format with +, e.g. +919876543210.",
    "field": "to.phone",
    "docs": "https://wbiztool.com/docs/api/v2/errors/#invalid_phone",
    "request_id": "req_4f1c2a9b8e7d6c5b4a392817"
  }
}
  • code не меняется: опирайтесь на него в своём коде. message — текст на английском для разработчика, он может меняться.
  • field называет поле, к которому относится ошибка (to.phone, to[3].phone, schedule.cron), или равен null.
  • docs ведёт к описанию кода на странице ошибок.
  • request_id совпадает с заголовком X-Request-Id. Укажите его, если обращаетесь к нам.
  • Некоторые ошибки добавляют подробности, например status у not_cancellable или used и limit у storage_full. Если в запросе несколько проблем, errors перечисляет остальные, каждую с field и message.

Все коды, их статусы HTTP и что делать, описаны на странице ошибок.

Idempotency-Key#

После сетевой ошибки или тайм-аута непонятно, сработал ли запрос. Передайте заголовок Idempotency-Key с запросом POST, который что-то создаёт, и его можно будет безопасно отправить ещё раз:

curl -X POST https://wbiztool.com/api/v2/messages \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-ready" \
  -d '{"to": {"phone": "+919876543210"}, "text": "Hi Asha, your order #1042 is ready."}'
  • Значение выбираете вы: любая уникальная строка из 1–255 печатаемых символов, например UUID или ваш собственный номер заказа. Создавайте новое значение для каждого нового запроса и используйте его повторно только для повтора того же запроса.
  • Повтор получает первый ответ с заголовком Idempotent-Replayed: true. Ничего не выполняется дважды: ни второго сообщения, ни напоминания, ни файла, ни endpoint.
  • Ключи живут 24 часа с первого запроса и принадлежат вашему API-ключу: другой API-ключ рабочего пространства может использовать то же значение без конфликта.
  • Тот же ключ, другой запрос: запрос с ключом, который уже использовался для другого метода, пути или тела, возвращает 422 idempotency_key_reused.
  • Ещё выполняется: пока первый запрос с этим ключом ещё обрабатывается, повтор возвращает 409 idempotency_in_progress с Retry-After: 1. Подождите немного и отправьте его снова.
  • Ошибки не сохраняются. Если первый запрос вернул ошибку, ничего не сохраняется: исправьте запрос и отправьте его снова с тем же ключом.
  • Секреты не повторяются. Повтор POST /webhooks не содержит secret endpoint: он показывается только в первом ответе.

Это работает для POST /messages, POST /messages/batch, POST /numbers, POST /reminders, POST /media, POST /number-checks и POST /webhooks и везде необязательно. Другие запросы игнорируют этот заголовок. Пустое или слишком длинное значение возвращает 400 invalid_idempotency_key.

Лимиты запросов#

Каждый ключ может делать 60 запросов в минуту и 10 000 запросов в день. Окна фиксированные: минутное окно начинается с начала минуты по часам, суточное — в 00:00 UTC. При превышении лимита запрос возвращает 429 rate_limited.

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

ЗаголовокЗначение
RateLimit-LimitСколько запросов разрешено в текущем окне (60 или 10000, когда достигнут суточный лимит)
RateLimit-RemainingСколько запросов осталось в этом окне
RateLimit-ResetЧерез сколько секунд это окно начнётся заново
RateLimit-PolicyОба лимита: 60;w=60, 10000;w=86400
Retry-AfterПри 429: сколько секунд подождать перед новой попыткой

Отдельно от этого:

  • Неверные ключи: больше 30 запросов в минуту с неверным ключом с одного IP-адреса возвращают 429 too_many_auth_failures с Retry-After: 60.
  • Сообщения на номер: номер отправляет не больше 1000 сообщений за 24 часа (честное использование). Отправка сверх этого возвращает 429 number_daily_cap_reached.

Пагинация#

Списки, которые могут расти (GET /messages, /reminders, /media, /number-checks и /results проверки), приходят страницами, сначала самые новые:

{
  "data": [ … ],
  "next_cursor": "eyJpZCI6OTgxNzI2MywidCI6IjIwMjYtMTAtMThUMTA6MTU6MDIuMzExWiIsImYiOiI0NGIxMzZmYTM1NWIifQ"
}
  • limit задаёт размер страницы, от 1 до 100 (по умолчанию 25).
  • Чтобы получить следующую страницу, отправьте тот же запрос с cursor, равным next_cursor предыдущей страницы. На последней странице next_cursor равен null.
  • Не меняйте остальные фильтры: курсор с другими фильтрами возвращает 400 invalid_cursor. Начните заново без курсора.
  • Считайте курсор непрозрачной строкой. Элементы, добавленные, пока вы листаете страницы, не сдвигают страницы.
curl "https://wbiztool.com/api/v2/messages?limit=100&cursor=eyJpZCI6OTgxNzI2MywidCI6..." \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

GET /numbers и GET /webhooks возвращают всё одним списком data.

ID запросов#

У каждого ответа, включая ошибки, есть заголовок X-Request-Id, например req_4f1c2a9b8e7d6c5b4a392817. В ошибках то же значение приходит как request_id. Записывайте его в лог и указывайте, если обращаетесь к нам: по нему мы найдём запрос в наших логах, где записан ID вашего ключа, но никогда не сам ключ.

Если вы передаёте собственный X-Request-Id (до 100 печатаемых символов), он возвращается как X-Client-Request-Id, чтобы вы могли сопоставить ответы со своими логами.

Тестовый режим#

Тестовый ключ (wbz_test_…) позволяет создавать и проверять интеграцию, ничего не отправляя. Создайте его на странице Настройки → API-ключи с Тип ключа: Тестовый. GET /me показывает "mode": "test".

Что тестовый ключ делает так же, как рабочий:

  • POST /messages и POST /messages/batch проверяют всё, что проверяет настоящая отправка: получателя, текст, медиафайл, send_at и expires_at, номер отправителя, области доступа и номера ключа. Одни и те же ошибки дают одни и те же коды.
  • Области доступа, номера, лимиты запросов и Idempotency-Key работают так же.
  • Любое чтение остальных данных рабочего пространства (GET /me, /numbers, /reminders, /media, /number-checks, /webhooks) показывает реальные данные, только для чтения.

Чем он отличается:

  • Ничего не отправляется. Тестовая отправка сохраняется как тестовое сообщение и не расходует ни сообщения тарифа, ни суточные 1000 номера, поэтому никогда не получает no_credits или number_daily_cap_reached.
  • Его статус меняется сам: queued, затем sent через 5 секунд и delivered через 15 секунд после создания (для запланированного — считая от send_at). Сообщение, у которого expires_at наступает раньше отправки, становится expired. Тестовые сообщения никогда не становятся read или failed.
  • Тестовый ключ видит только свои тестовые сообщения. GET /messages и GET /messages/{id} показывают их и ничего больше, а DELETE /messages/{id} отменяет сообщение, пока оно queued или scheduled. Рабочие ключи никогда не видят тестовых сообщений. Фильтр status в GET /messages для тестовых ключей не поддерживается и возвращает test_mode_unsupported; number, since и until работают.
  • Остальные изменения отклоняются с 403 test_mode_unsupported: подключение номера, создание, изменение и удаление напоминаний, загрузка и удаление медиафайлов, запуск проверки номеров, добавление, удаление, замена секрета и тестирование webhook endpoint.
  • События вебхуков для тестовых сообщений не отправляются.
  • Тестовые сообщения хранятся 30 дней.

Ресурсы#

  • Сообщения: отправка сейчас или позже, отправка до 1000 получателям, история, отмена.
  • Номера: список ваших номеров WhatsApp и аккаунтов Telegram, подключение номера WhatsApp по QR-коду или коду привязки.
  • Напоминания: повторяющиеся сообщения по расписанию cron.
  • Медиафайлы: загрузите файлы один раз и отправляйте их по media_id.
  • Проверки номеров: узнайте, какие номера есть в WhatsApp.
  • Вебхуки: подписанные события, когда сообщение отправлено, не отправлено, отменено или истекло.
  • Ошибки: все коды ошибок.
  • Переход с v1 на v2: каждый endpoint и каждое поле v1 и их аналоги в v2.