API v2, в формате WhatsApp Cloud API

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

Отправляйте шаблоны и сообщения WhatsApp из своей системы, получайте входящие и статусы на свой адрес. Один ключ, обычные HTTP-запросы и JSON.

Базовый адрес: https://wazzapo.kz/api/v2/external

Разделы документации

Быстрый старт

Четыре шага от регистрации до первого сообщения клиенту.
  1. 1

    Создайте кабинет

    Зарегистрируйтесь на wazzapo.kz и выберите тариф.

  2. 2

    Получите ключ

    Кабинет → API → «Создать ключ». Ключ показывается один раз, сохраните его.

  3. 3

    Подключите номер

    Через официальное окно Meta в разделе «Каналы» или методом POST /phone-numbers.

  4. 4

    Отправьте сообщение

    Первым сообщением клиенту отправляется одобренный Meta шаблон.

Ключ доступа

Каждый запрос передаёт ключ в заголовке X-API-Key. Ключ создаётся в кабинете, в разделе API.

Показывается один раз

Сохраните ключ сразу после создания. Ключи вида wz_live_...

Храним только хэш

Сам ключ у нас не хранится, только его отпечаток для проверки.

Удаление сразу

Удалённый или выключенный ключ перестаёт работать с первого запроса.

Проверка ключа: список номеров
curl https://wazzapo.kz/api/v2/external/phone-numbers \  -H "X-API-Key: wz_live_..."# Ответ 200{  "data": [    {      "phone_number_id": "103799815708451",      "display_phone_number": "+7 700 123 4567",      "verified_name": "Wazzapo Demo",      "quality_rating": "GREEN",      "code_verification_status": "VERIFIED",      "status": "connected",      "provider_type": "whatsapp_business"    }  ],  "meta": {}}

Первое сообщение

Первым сообщением клиенту, который вам ещё не писал, отправляется одобренный Meta шаблон. Пример запросом и через библиотеки SDK.
bash
# phone_number_id возьмите из GET /phone-numbers# template.name: имя одобренного Meta шаблонаcurl -X POST https://wazzapo.kz/api/v2/external/messages/send \  -H "X-API-Key: wz_live_..." \  -H "Content-Type: application/json" \  -d '{    "phone_number_id": "103799815708451",    "to": "77001234567",    "type": "template",    "template": {      "name": "order_ready",      "language": { "code": "ru" },      "components": [        {          "type": "body",          "parameters": [            { "type": "text", "text": "Айдар" },            { "type": "text", "text": "12345" }          ]        }      ]    }  }'# Ответ{ "message_id": "...", "provider_message_id": "wamid.HBg...", "status": "accepted" }

Если клиент написал вам за последние 24 часа, можно ответить обычным текстом: "type": "text". Файлы отправляются так же: image, video, audio или document с публичной ссылкой в поле link.

Тело запроса: ответ текстом
{  "phone_number_id": "103799815708451",  "to": "77001234567",  "type": "text",  "text": { "body": "Здравствуйте! Заказ готов к выдаче." }}

Если в шапке шаблона картинка, видео или документ, файл передаётся в каждой отправке: ссылка в link или id из POST /media. Сумма передаётся как currency (amount_1000: сумма, умноженная на 1000), окончание ссылки кнопки как button с sub_type: url.

Тело запроса: шаблон с картинкой, суммой и кнопкой
{  "phone_number_id": "103799815708451",  "to": "77071234567",  "type": "template",  "template": {    "name": "osennyaya_aktsiya",    "language": { "code": "ru" },    "components": [      {        "type": "header",        "parameters": [{ "type": "image", "image": { "link": "https://example.kz/promo/osen.jpg" } }]      },      {        "type": "body",        "parameters": [          { "type": "text", "text": "Ерлан" },          { "type": "currency", "currency": { "fallback_value": "15 000 ₸", "code": "KZT", "amount_1000": 15000000 } }        ]      },      { "type": "button", "sub_type": "url", "index": 0, "parameters": [{ "type": "text", "text": "osen25" }] }    ]  }}

Библиотеки SDK

Официальные библиотеки для PHP, JavaScript и Python. Код открыт, лицензия MIT. Методы и поля те же, что в API, с подсказками по-русски в редакторе.

Первый запрос за 5 минут: ключ из кабинета положите в переменную WAZZAPO_API_KEY, возьмите номер WhatsApp и отправьте текст.

php
<?php// composer require wazzapo/wazzapo-phprequire 'vendor/autoload.php';$client = new Wazzapo\Wazzapo(['api_key' => getenv('WAZZAPO_API_KEY')]);// Номер WhatsApp, с которого отправлять$number = $client->phoneNumbers->list(['channel' => 'whatsapp'])['data'][0];// Текст доходит, если клиент писал вам за последние 24 часа$sent = $client->messages->send([    'phone_number_id' => $number['phone_number_id'],    'to' => '77071234567',    'type' => 'text',    'text' => ['body' => 'Айгуль, здравствуйте! Запись на 25 октября в 15:00 подтверждена.'],]);echo $sent['message_id'];

Что библиотека делает сама

  • Повторяет запрос сама

    При 429, 5xx и сбое сети ждёт и повторяет, учитывает Retry-After.

  • Не отправит дважды

    Ставит Idempotency-Key на каждый POST, один и тот же во всех повторах.

  • Ошибки по классам

    OutsideWindowError, RateLimitError, ValidationError и другие (в PHP с окончанием Exception): с кодом, подробностями и request_id.

  • Списки целиком

    listAll в PHP и JavaScript, list_all в Python проходят все страницы по next_cursor.

  • Подпись вебхука

    Проверяет X-Wazzapo-Signature-V2 и время отправки, сравнение за постоянное время.

  • Тестовый ключ

    С ключом wz_test_ запросы ничего не отправляют и не меняют, ответы как у настоящего.

Коллекция Postman

Все методы с примерами тел запросов. Импортируйте файл и вставьте тестовый ключ в переменную apiKey.

Скачать коллекцию

MCP для нейросетей

Claude и другие ИИ-помощники через MCP читают диалоги, отправляют шаблоны, ведут сделки и задачи.

Как подключить

Методы API

Пути указаны от базового адреса https://wazzapo.kz/api/v2/external. Тела запросов и ответов в JSON.

Номера

  • GET/phone-numbers

    Подключённые номера: качество (quality_rating), подтверждение и статус.

  • GET/phone-numbers/{phone_number_id}

    Один номер.

  • POST/phone-numbers

    Начать подключение нового номера. В ответе может прийти embedded_signup_url: ссылка на окно Meta.

    display_namephone_e164
  • DELETE/phone-numbers/{phone_number_id}

    Отключить номер.

  • GET/phone-numbers/{phone_number_id}/business-profile

    Профиль компании в WhatsApp.

Сообщения

  • POST/messages/send

    Шаблон, текст или файл. Файл по ссылке (link) или по media_id из POST /media (id), ровно одно из двух. Сообщение сразу видно в переписке кабинета. Текст и файлы доходят только в течение 24 часов после сообщения клиента, вне этого окна нужен шаблон.

    phone_number_idtotypetemplate | text | image | video | audio | document
  • POST/messages/send

    Шаблон с переменными: template.components со значениями по порядку {{1}}, {{2}}. Виды значений как в WhatsApp Cloud API: text (и parameter_name для именованных переменных), currency {fallback_value, code, amount_1000}, date_time {fallback_value}, файл шапки image, video, document {id или link, filename}, location. Кнопки: type button, sub_type quick_reply (payload), url (text: окончание ссылки), copy_code (coupon_code), index с 0. Файл шапки передаётся в каждой отправке.

    template.nametemplate.language.codetemplate.components[].typetemplate.components[].parameterssub_typeindex
  • POST/messages/send

    Кнопки, список, ссылка-кнопка, запрос места, место, контакт, стикер. Формат как в WhatsApp Cloud API: interactive.type button (до 3 кнопок, надпись до 20 знаков), list (до 10 строк во всех разделах), cta_url, location_request_message. Ответ на сообщение: context.message_id. Нажатие клиента придёт в message.incoming, поле interactive {type, id, title}.

    phone_number_idtotypeinteractive | location | contacts | stickercontexttext.preview_url
  • POST/messages/mark-read

    Отметить входящие прочитанными (синие галочки): wamid из вебхука message.incoming.

    phone_number_idmessage_ids
  • POST/messages/reaction

    Поставить реакцию на сообщение, пустой emoji снимает её.

    phone_number_idtomessage_idemoji

Шаблоны

  • GET/templates

    Шаблоны номера со статусом проверки Meta и содержимым (components, variables_count). По 50 на страницу: следующая по cursor=next_cursor. Фильтры можно сочетать: status, category, name (часть имени), language.

    phone_number_idstatuscategorynamelanguagelimitcursor
  • POST/templates

    Отправить новый шаблон на проверку Meta. name: латиница в нижнем регистре, цифры и _, например zapis_napominanie. Части: HEADER (TEXT до 60 знаков, IMAGE, VIDEO, DOCUMENT, LOCATION), BODY (до 1024 знаков, переменные {{1}}, {{2}} не в начале и не в конце, пример в example.body_text), FOOTER (до 60), BUTTONS (до 10: QUICK_REPLY, URL, PHONE_NUMBER, COPY_CODE, OTP для кода подтверждения). Картинку, видео или PDF в шапке передайте ссылкой в example.media_url: Wazzapo сам загрузит образец в Meta. Пропуск обязательного поля: 422 VALIDATION_ERROR до отправки в Meta.

    phone_number_idnamelanguagecategorycomponents
  • GET/templates/{template_id}

    Шаблон целиком: части, вид шапки, сколько переменных передать при отправке, кнопки. Статус свежий из Meta.

  • PATCH/templates/{template_id}

    Изменить шаблон в статусе APPROVED, REJECTED или PAUSED: components заменяются целиком, имя и язык не меняются, категорию одобренного сменить нельзя. Одобренный правится раз в сутки и до 10 раз за 30 дней. После правки Meta проверяет шаблон заново.

    categorycomponents
  • GET/templates/{template_id}/status

    Статус проверки: PENDING, APPROVED, REJECTED, DISABLED, PAUSED.

  • DELETE/templates/{template_id}

    Удалить шаблон.

Файлы

  • POST/media

    Загрузить файл до 100 МБ (поле file, multipart). В ответе media_id: передайте его в /messages/send как id.

    phone_number_id
  • GET/media/{media_id}

    Скачать файл из входящего сообщения.

    phone_number_id

Воронки, сделки и задачи

  • GET/pipelines

    Начните с него: отсюда pipeline_id (id), stage_id (stages[].id) и id своих полей для custom_fields (custom_fields[].id, тип и варианты options). Поле с is_amount: true хранит сумму сделки. Право deals:read.

  • GET/deals

    Сделки по времени изменения, старые первыми. Для синхронизации передавайте updated_since. Дубль перед созданием ищите по external_id. Сумма amount целым в тиынах: 150 000 ₸ = 15000000. Право deals:read.

    pipeline_idstage_idcontact_idexternal_idupdated_sincelimitcursor
  • GET/deals/{deal_id}

    Одна сделка: этап, сумма, клиент, ответственный, свои поля. Скрытая от сотрудника с ключом: 404 deal_not_found.

  • POST/deals

    Создать сделку, например из заявки с сайта. Клиент по contact_id из GET /contacts или contact {phone, name}: найдём по номеру или создадим. Без stage_id первый этап. Ответственный: id из GET /team. custom_fields: ключ это id поля из GET /pipelines, значение по типу (деньги в тиынах, select строкой из options, дата ГГГГ-ММ-ДД). Повтор с тем же Idempotency-Key сделку не дублирует. Право deals:write.

    pipeline_idstage_idtitleamountcurrencycontact_idcontactresponsible_user_idcustom_fieldsexternal_id
  • PATCH/deals/{deal_id}

    Изменить название, сумму, ответственного, свои поля, external_id. Меняются только переданные поля, null в custom_fields очищает поле. Этап меняет move.

    titleamountcurrencyresponsible_user_idcustom_fieldsexternal_id
  • POST/deals/{deal_id}/move

    Перенести на этап своей воронки. Срабатывают сценарии и действия этапа, вебхуки deal.stage_changed и deal.closed, передача продажи в Meta, как при переносе в кабинете. Поля, обязательные с этапа, заполните заранее через PATCH, иначе 422 required_fields.

    stage_idpipeline_idlost_reason
  • GET/deals/{deal_id}/tasks

    Задачи сделки по сроку, вместе с выполненными. Право tasks:read.

    limitcursor
  • POST/deals/{deal_id}/tasks

    Поставить задачу. Срок due_at в ISO 8601: Казахстан живёт по UTC+5, «завтра в 10:00 по Астане» это 05:00Z или 10:00:00+05:00. По умолчанию исполнитель ответственный сделки. Право tasks:write.

    titledue_atresponsible_user_idtask_typedescription
  • PATCH/tasks/{task_id}

    Изменить название, срок, исполнителя. done: true отмечает выполненной, false возвращает в работу.

    titledue_atresponsible_user_iddone

Пример: заявка с сайта в сделку без дублей

bash
# pipeline_id, stage_id и id своих полей возьмите из GET /pipelines,# responsible_user_id из GET /team. amount в тиынах: 150 000 ₸ = 15000000curl -X POST https://wazzapo.kz/api/v2/external/deals \  -H "X-API-Key: wz_live_..." \  -H "Idempotency-Key: site-order-4521" \  -H "Content-Type: application/json" \  -d '{    "pipeline_id": "6712a0c4e1b2c3d4e5f60718",    "stage_id": "a1b2c3d4e5f6a7b8c9d0e1f2",    "title": "Заявка с сайта: кухня на заказ",    "amount": 15000000,    "contact": { "phone": "77071234567", "name": "Айгуль Сейткали" },    "responsible_user_id": "12",    "external_id": "site-order-4521",    "custom_fields": { "9c8b7a6d5e4f": "Сайт", "3e4f5a6b7c8d": "Астана" }  }'# Ответ 201: сделка с id, number, stage_name, contact.id

Диалоги

  • GET/conversations

    Диалоги из всех каналов (whatsapp, telegram, instagram, webchat, olx, satu, email) по updated_at от старых к новым. Синхронизация: первый раз листайте по cursor=next_cursor, пока has_more не станет false, затем передавайте в updated_since updated_at последнего диалога. assignee_user_id=none: без ответственного.

    phone_number_idchannelstatusassignee_user_idunreadupdated_sincelimitcursor
  • GET/conversations/{conversation_id}

    Один диалог: контакт, канал, статус, ответственный, метки (tags), непрочитанные и последнее сообщение. Статусы: open (нужно ответить), pending (ожидает), snoozed (отложен), resolved (решён); новое сообщение клиента снова открывает диалог.

  • GET/conversations/{conversation_id}/messages

    Переписка от старых к новым, кто написал в sender.type (contact, manager, workflow, chatbot, broadcast, api). Только новые: since = timestamp последнего полученного. Заметки сотрудников только с include_notes=true. У шаблонных сообщений template: имя, язык, переменные.

    include_notessincelimitcursor
  • POST/conversations/{conversation_id}/assign

    Назначить ответственного: {"user_id": "7"}, id из GET /team; null снимает. Новому ответственному уведомление в кабинете, вебхук conversation.assigned.

    user_id
  • POST/conversations/{conversation_id}/status

    Закрыть диалог: {"status": "resolved"} (клиенту запрос оценки, если включён). Отложить: snoozed и snoozed_until. Вебхук conversation.status_changed.

    statussnoozed_until
  • POST/conversations/{conversation_id}/notes

    Заметка видна только сотрудникам, клиенту не уходит. Упомянутым в mention_user_ids (id из GET /team) уведомление. Повтор с тем же Idempotency-Key не создаёт вторую. Вебхук conversation.note_added.

    textmention_user_ids
  • POST/conversations/{conversation_id}/labels

    Метки заменяют прежний список целиком: чтобы добавить, передайте старые и новую; [] убирает все. Копируются в контакт, в ответе поле tags.

    labels

Сотрудники

  • GET/team

    Владелец и сотрудники: id для user_id в /assign и mention_user_ids в заметках, имя, роль (owner, ADMIN, AGENT, VIEWER), is_active (на отключённых не назначить), phone_number_ids (null: все номера). Без почты и телефонов.

    limitcursor

Контакты

  • GET/contacts

    Контакты аккаунта, старые первыми. search ищет по части имени или номера (8 707 123 45 67 тоже найдётся), tag по метке, updated_since изменённые с даты, external_id по вашему id из своей CRM. По 50 на страницу: следующая по cursor=next_cursor.

    searchtagupdated_sinceexternal_idlimitcursor
  • GET/contacts/{contact_id}

    Один контакт: номер (цифры с кодом страны, 77071234567), имя, email, метки, свои поля, source (manual, whatsapp, import, api, email: как появился), attribution (first и last: откуда пришёл клиент, реклама Meta, метки сайта, ссылка с меткой), ваш external_id.

  • POST/contacts

    Создать контакт. Номер цифрами с кодом страны: плюс можно, 8 в начале заменяется на 7. custom_fields по имени переменной из раздела «Поля контакта» кабинета, например {"city": "Алматы"}. external_id: ваш id из своей CRM, не обязан быть уникальным. Номер уже есть: 409 contact_exists, id в error.details.contact_id, измените его через PATCH. Удалённый ранее контакт восстанавливается.

    phonenameemailtagscustom_fieldsexternal_id
  • PATCH/contacts/{contact_id}

    Изменить переданные поля, номер не меняется. tags заменяют весь список. custom_fields дополняют сохранённые, null очищает поле.

    nameemailtagscustom_fieldsexternal_id
  • DELETE/contacts/{contact_id}

    Мягкое удаление, как в кабинете: контакт пропадает из списка, переписка остаётся. Новое сообщение с номера или POST /contacts с тем же номером вернут его.

Вебхуки

  • GET/webhook-event-types

    Каталог событий: имя для event_types, когда приходит и пример поля data.

  • GET/webhooks

    Подписки аккаунта, в том числе созданные в кабинете и через API v1.

    limitcursor
  • POST/webhooks

    Подписаться на события, например message.incoming и deal.stage_changed. Адрес только https:// и публичный. Секрет подписи приходит один раз, в этом ответе: сохраните его. Отвечайте 2xx за 10 секунд, иначе повторы через 1 мин, 5 мин, 30 мин, 2 ч и 6 ч.

    urlevent_typesdescription
  • GET/webhooks/{webhook_id}

    Одна подписка, без секрета.

  • PATCH/webhooks/{webhook_id}

    Изменить адрес, события (список заменяется целиком) или выключить: is_active=false. После 10 доставок подряд, не дошедших за все попытки, вебхук выключается сам; is_active=true включает и обнуляет счётчик ошибок.

    urlevent_typesis_activedescription
  • DELETE/webhooks/{webhook_id}

    Удалить подписку и историю доставок.

  • POST/webhooks/{webhook_id}/test

    Отправить тестовое событие и получить ответ вашего сервера.

  • POST/webhooks/{webhook_id}/rotate-secret

    Новый секрет подписи. Старый перестаёт действовать сразу.

  • GET/webhooks/{webhook_id}/deliveries

    История доставок, новые первыми: статус (success, retry_scheduled, failed), попытка, ответ вашего сервера, время следующего повтора. id доставки совпадает с заголовком X-Wazzapo-Delivery-Id.

    limitcursor
  • POST/webhooks/{webhook_id}/deliveries/{delivery_id}/retry

    Повторить доставку сейчас, например после починки приёмника.

Вебхуки

Wazzapo отправляет POST-запрос на ваш адрес при каждом выбранном событии. Адрес и события задаются в кабинете: раздел API, вкладка «Вебхуки».

События

  • message.incoming

    Клиент написал: WhatsApp, Telegram, Instagram, OLX, почта, чат на сайте (поле channel)

  • message.outgoing

    Любое сообщение клиенту; кто отправил, в поле sender.type

  • message.status

    Статус исходящего: отправлено, доставлено, прочитано, ошибка

  • conversation.assigned

    Диалог назначили, передали или сняли назначение

  • conversation.status_changed

    Статус диалога: open, pending, snoozed, resolved

  • conversation.note_added

    Заметка менеджера в диалоге, только по явной подписке

  • session.connected

    Номер подключён

  • session.disconnected

    Номер отключён

  • deal.stage_changed

    Сделку перевели на другой этап

  • deal.closed

    Сделка выиграна или проиграна

  • deal.created

    Новая сделка: из карточки, правилом, сценарием или через API

  • deal.changed

    У сделки поменялись сумма, название, ответственный, клиент или поля (не этап)

  • contact.created

    Новый контакт; импорт из файла событий не шлёт

  • contact.updated

    Изменили карточку контакта: что было и что стало в changes

  • template.status_updated

    Meta проверила шаблон: APPROVED, REJECTED, PAUSED, DISABLED

  • template.quality_changed

    Meta изменила качество шаблона: GREEN, YELLOW, RED

  • template.category_changed

    Meta сменила категорию шаблона, от неё зависит цена

  • invoice.status_changed

    Счёт Kaspi сменил статус: оплачен, отменён, истёк, ошибка; сумма в тиынах

  • task.created

    Новая задача менеджеру

Тело запроса всегда одинаковое: event, timestamp и данные события в data. В примерах ниже часть полей сокращена, полный пример каждого события есть в кабинете.

Входящее сообщение
POST https://your-app.kz/webhookContent-Type: application/jsonX-Wazzapo-Event: message.incomingX-Wazzapo-Delivery-Id: 6a7d5d3712f8e1a5c19f40e9X-Wazzapo-Attempt: 1X-Wazzapo-Signature: sha256=5f2c...X-Wazzapo-Timestamp: 1790671502X-Wazzapo-Signature-V2: v2=9b1e...{  "event": "message.incoming",  "timestamp": "2026-09-29T09:15:02+00:00",  "data": {    "channel": "whatsapp",    "phone_number_id": "103799815708451",    "conversation_id": "6a7d5d3712f8e1a5c19f40c4",    "contact": { "id": "6a7d5d37...", "phone": "77051450954", "name": "Айгерим" },    "message": {      "id": "wamid.HBg...",      "from": "77051450954",      "type": "text",      "text": "Сколько стоит?",      "timestamp": "2026-09-29T09:14:40+00:00"    }  }}
Статус доставки
{  "event": "message.status",  "timestamp": "2026-09-29T09:15:05+00:00",  "data": {    "phone_number_id": "103799815708451",    "conversation_id": "6a7d5d3712f8e1a5c19f40c4",    "message_id": "wamid.HBg...",    "status": "delivered",    "error": null  }}

Проверяйте подпись

В заголовке X-Wazzapo-Timestamp приходит время отправки в unix-секундах, в X-Wazzapo-Signature-V2 подпись v2=...: HMAC-SHA256 строки {timestamp}.{тело} с секретом вебхука. Считайте подпись по сырому телу запроса, сравнивайте за постоянное время и не принимайте запросы старше 5 минут: так перехваченный запрос не повторить позже. Запросы с неверной подписью не обрабатывайте.

Прежняя подпись X-Wazzapo-Signature: sha256=... (HMAC-SHA256 только тела) приходит по-прежнему. Поле timestamp в теле означает время события и одинаково во всех повторах.

python
import hashlib, hmac, timedef is_valid(secret: str, body: bytes, timestamp: str, signature: str) -> bool:    # timestamp: X-Wazzapo-Timestamp, signature: X-Wazzapo-Signature-V2 ("v2=9b1e...")    # body: сырое тело запроса, до разбора JSON    if abs(time.time() - int(timestamp)) > 300:  # допуск 5 минут        return False    signed = timestamp.encode() + b"." + body    expected = "v2=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()    return hmac.compare_digest(expected, signature)
node.js
const crypto = require("crypto");// rawBody: Buffer с сырым телом запроса, например express.raw({ type: "application/json" })function isValid(secret, rawBody, timestamp, signature) {  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; // допуск 5 минут  const expected = "v2=" + crypto    .createHmac("sha256", secret)    .update(timestamp + ".")    .update(rawBody)    .digest("hex");  const a = Buffer.from(expected);  const b = Buffer.from(signature || "");  return a.length === b.length && crypto.timingSafeEqual(a, b);}

Отвечайте за 10 секунд

Верните код 2xx сразу, а событие обработайте в фоне. Дольше 10 секунд считается ошибкой.

Повторы

При ошибке ещё 5 попыток: через 1 мин, 5 мин, 30 мин, 2 ч и 6 ч. Если подряд не удалось доставить 10 событий, вебхук выключается.

Дубли

X-Wazzapo-Delivery-Id одинаков у всех повторов одного события. Сохраняйте его и пропускайте уже обработанные.

Лимиты и ошибки

Число сообщений тариф не ограничивает. Ограничено число запросов к API в минуту, оно зависит от тарифа.

Стартовый

60

запросов в минуту

Бизнес

200

запросов в минуту

Про

600

запросов в минуту

Корпоративный

2 000

запросов в минуту

Ошибка всегда приходит в одном виде. Ориентируйтесь на error.code, полный список кодов в описании OpenAPI. Частые случаи:

Тело ошибки
{"success": false, "error": {"code": "outside_24h_window", "message": "…", "details": {}}, "request_id": "…"}
  • 401INVALID_API_KEY: нет ключа или ключ неверный, выключен или удалён.
  • 402payment_required: тариф Wazzapo не оплачен. meta_payment_required: Meta не может списать оплату.
  • 403INSUFFICIENT_SCOPE, IP_NOT_ALLOWED, USAGE_LIMIT_EXCEEDED: нет права у ключа, IP не разрешён или исчерпан лимит тарифа.
  • 404Номер или шаблон не найден в вашем аккаунте.
  • 422VALIDATION_ERROR или отказ Meta: outside_24h_window, template_not_found, recipient_unavailable и другие. IDEMPOTENCY_KEY_REUSED: Idempotency-Key уже использован с другим телом запроса.
  • 429RATE_LIMIT_EXCEEDED: лимит запросов в минуту, повторите через Retry-After секунд. В каждом ответе есть X-RateLimit-Limit, X-RateLimit-Remaining и X-RateLimit-Reset. rate_limited: Meta ограничила частоту.
  • 501not_supported: метод не поддерживается для этого подключения.
  • 502provider_error: сбой на стороне Meta, повторите позже.

Полезные статьи

Подключение номера, шаблоны и правила Meta подробно в «Помощи».

Вопросы

Есть описание API для Postman и генерации кода?

Да, OpenAPI 3.1: https://wazzapo.kz/api/v2/external/openapi.json, интерактивно: https://wazzapo.kz/api/v2/external/docs. Готовая коллекция Postman: wazzapo.kz/sdk/wazzapo-api-v2.postman_collection.json. Для PHP, JavaScript и Python есть библиотеки, см. раздел «Библиотеки SDK».

Как начать работать с API?

Создайте ключ в кабинете: раздел API. Передавайте его в заголовке X-API-Key. Базовый адрес: https://wazzapo.kz/api/v2/external.

Сколько сообщений можно отправить?

Тариф Wazzapo число сообщений не ограничивает. Сообщения оплачиваются Meta напрямую с вашей карты по её ценам. Ограничено только число запросов к API в минуту, оно зависит от тарифа.

Как хранятся ключи?

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

Можно получать входящие сообщения?

Да, через вебхуки. В кабинете в разделе API на вкладке «Вебхуки» укажите адрес и выберите события. Мы отправим POST-запрос на каждое событие.

Можно связать с CRM?

amoCRM и Bitrix24 подключаются готовыми интеграциями в разделе «Интеграции». Остальные системы подключаются через API и вебхуки.

Готовы подключить API?

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