WhatsApp API
Принимайте входящие сообщения на свой сервер и отправляйте ответы из любой системы — n8n, Make, свой бэкенд или скрипт.
Подойдёт для интеграции с CRM, чат-ботами, автоматизациями. Нужен только HTTP — без SDK и библиотек.
С чего начать за 30 секунд
- Каждый номер = свой ключ
api_key. Он приходит в каждом входящем событии и им же вы скачиваете файлы и отправляете ответы. Вручную сопоставлять «номер → ключ» не нужно. - Входящие. Мы отправляем
POSTна ваш адрес (webhook URL) при каждом новом сообщении — в удобном плоском формате. - Исходящие. Вы отправляете
POSTнаhttps://my.goflow.kz/api/messagesс заголовкомX-API-Key. - Куда отвечать — всегда в
chat_idиз входящего. Кто написал — всегда вsender(телефон).
instance (это номер-получатель), а отвечайте ключом api_key из того же входящего — настраивать ничего не придётся.Подключение номера
- Подключите номер. Официальный (WhatsApp Business API) — в разделе «Интеграции», обычный — по QR-коду в разделе «Мои номера». Вебхук работает одинаково на обоих.
- Включите модуль «Вебхук / API» (без него раздел с ключом скрыт).
- Откройте в кабинете «Настройки → API и вебхуки», выберите номер в списке сверху и заполните блок «Вебхук»:
- Включить webhook — отправлять ли события на ваш адрес.
- URL — куда мы шлём входящие, например
https://your-n8n.com/webhook/abc. - Входящие сообщения — получать ли их в вебхук (если выключить, придут только служебные события вроде подключения).
- Звонки — получать ли события входящих звонков (по умолчанию выключено; см. раздел «Входящий звонок»).
- Только лиды с рекламы — присылать не всю переписку, а только сообщения с меткой рекламы Meta. Есть у официальных номеров. 🔴 Метка приходит лишь с первым сообщением человека, поэтому его следующие сообщения в вебхук не поедут (см. раздел «Метка рекламы»).
- События сделок — присылать событие, когда сделку завели или она сменила этап (по умолчанию выключено, включаем по запросу). Там же выбираются этапы, которые вам нужны, и отдельная галочка «Новый лид» (см. раздел «События сделок»).
Настройки относятся к выбранному номеру. Нажмите «Сохранить настройки вебхука» — они применяются сразу.
- api_key номера показан на той же странице, в блоке «Ключ доступа» (значок «глаз» / «копировать»).
Поведение номера (необязательно, только для номера по QR-коду)
У номера, подключённого по QR-коду, есть отдельные настройки самого приложения WhatsApp: отклонять входящие звонки, игнорировать группы (тогда сообщения из групп вообще не приходят), всегда быть онлайн, отмечать сообщения прочитанными и т.д. Они живут на карточке номера в разделе «Мои номера», кнопка ⚙️ Настройки.
У официального номера (WhatsApp Business API) этих настроек нет и быть не может: там телефоном распоряжается Meta, а не кабинет. Групповые сообщения по этому пути не приходят вовсе.
Входящие сообщения (вебхук)
Когда на ваш номер приходит сообщение, мы отправляем на ваш URL запрос:
POST{ваш webhook URL}, Content-Type: application/json
Поля верхнего уровня
| Поле | Описание |
|---|---|
event | "message" · "reaction" · "call" · "connection" |
instance | Ваш номер-получатель в формате +77001234567 |
api_key | Ключ этого номера — им скачивать файлы и отправлять ответ |
provider | Откуда сообщение: "waba" — официальный номер WhatsApp Business API, "evolution" — обычный номер по QR-коду. Поля ниже помечены, если есть только у одного из них |
data | Разобранные данные сообщения (плоские поля, см. ниже) |
raw | Доп. поля сообщения: text, type, timestamp, quoted (цитируемое сообщение: text/sender/message_id). Только при event:"message" |
Поля внутри data
| Поле | Когда | Описание |
|---|---|---|
chat_id | всегда | Куда отвечать. Личка → чистый номер 77009876543. Группа → 120363...@g.us |
sender | всегда | Кто написал, всегда телефон. В группе — реальный номер участника |
sender_name | всегда | Имя отправителя (как в WhatsApp) |
is_group | всегда | true / false |
group_name | группы | Название группы |
message_id | всегда | ID сообщения |
from_me | всегда | true = это ваше исходящее (или отправленное с телефона) |
timestamp | всегда | Время в формате unix |
message_type | всегда | text · image · video · audio · document · sticker · location · contact |
text | текст/подпись | Текст сообщения или подпись к файлу |
caption | файл с подписью | Подпись (дублируется в text) |
mime_type | файлы | image/jpeg, video/mp4, application/pdf … |
file_name | документы | Имя файла (русские имена поддерживаются) |
media_url | файлы | Ссылка для скачивания (см. «Скачивание файлов») |
mentions | упоминания | Массив реальных номеров, кого упомянули: ["77007654321"] |
mention_all | @all | true — упомянули всех в группе |
latitude, longitude, location_name, address | локация | Координаты и название/адрес точки |
contact_name, vcard | контакт | Имя и карточка контакта (несколько → vcards[]) |
emoji, target_message_id | реакция | Эмодзи и ID сообщения, на которое поставили реакцию |
is_forwarded | официальный номер | true — сообщение переслано, а не написано самим человеком. Полезно, когда клиент кидает прайс конкурента или чужую переписку: по тексту это неотличимо |
is_voice | официальный номер | true — это голосовое, а не присланный аудиофайл. У обоих message_type: "audio", отличие только в этом поле |
system | смена номера | Человек сменил номер телефона в WhatsApp. Внутри: new_number — новый номер, previous_number — прежний (он же в chat_id), type — вид события у Meta. Приходит при message_type: "system" и ровно один раз |
referral | лид с рекламы | Метка клика по рекламе Meta: ctwa_clid, id объявления, его заголовок и ссылка. Приходит только с первым сообщением человека после клика — см. раздел «Метка рекламы» |
Примеры
Текстовое сообщение (личка):
{
"event": "message",
"instance": "+77001234567",
"api_key": "5ed944...",
"data": {
"chat_id": "77009876543",
"sender": "77009876543",
"sender_name": "Aigerim",
"is_group": false,
"message_id": "3EB0...",
"from_me": false,
"timestamp": 1780336892,
"message_type": "text",
"text": "Здравствуйте, заказ готов?"
}
}Сообщение в группе с упоминанием:
{
"event": "message",
"instance": "+77001234567",
"api_key": "5ed944...",
"data": {
"chat_id": "120363000000000000@g.us",
"sender": "77009876543",
"sender_name": "Aigerim",
"is_group": true,
"group_name": "Доставка · смена",
"message_id": "...",
"from_me": false,
"message_type": "text",
"text": "@77001234567 принимай заказ",
"mentions": ["77001234567"]
}
}text уже стоит реальный номер (@77001234567), а в mentions — те же номера списком. Если упомянули всех (@all) — придёт "mention_all": true.Картинка с подписью:
{
"event": "message",
"instance": "+77001234567",
"api_key": "5ed944...",
"data": {
"chat_id": "77009876543",
"sender": "77009876543",
"is_group": false,
"message_id": "2A52...",
"message_type": "image",
"text": "Вот чек",
"caption": "Вот чек",
"mime_type": "image/jpeg",
"media_url": "https://my.goflow.kz/api/messages/media/2A52..."
}
}- Документ: то же, но
message_type:"document",mime_type:"application/pdf",file_name:"Меню.pdf". - Видео / гифка:
message_type:"video",mime_type:"video/mp4". - Голосовое:
message_type:"audio",mime_type:"audio/ogg; codecs=opus".
Реакция на сообщение:
{
"event": "reaction",
"instance": "+77001234567",
"api_key": "...",
"data": {
"chat_id": "120363...@g.us",
"sender": "77009876543",
"is_group": true,
"emoji": "🔥",
"target_message_id": "2AF1..."
}
}- Локация:
message_type:"location"+latitude,longitude,location_name,address. - Контакт:
message_type:"contact"+contact_name,vcard.
Подключение / отключение номера:
{
"event": "connection",
"instance": "+77001234567",
"api_key": "...",
"data": { "state": "connected" }
}Входящий звонок (вебхук)
Если в разделе «API и вебхуки» у номера включён тумблер «Звонки» (по умолчанию выключен), при входящем звонке на ваш URL приходит событие:
POST{ваш webhook URL}, поле event: "call"
Поля внутри data
| Поле | Описание |
|---|---|
caller | Кто звонит — номер звонящего, напр. 77009876543. Дублируется в chat_id, чтобы можно было сразу написать в ответ |
caller_resolved | true — в caller реальный телефон. false — WhatsApp скрыл номер и восстановить не удалось (в caller технический ID) |
caller_lid | Технический ID звонящего (когда WhatsApp прислал звонок в скрытом виде). Для трассировки; обычно номер уже восстановлен в caller |
call_id | ID звонка — один на весь звонок. По нему отсеивайте повторные события (см. ниже) |
status | Стадия: offer (зазвонил) → ringing → reject / terminate (завершился) |
is_video | true — видеозвонок |
is_group | true — групповой звонок |
timestamp | Время в формате unix |
Пример
{
"event": "call",
"instance": "+77001234567",
"api_key": "5ed944...",
"data": {
"caller": "77009876543",
"chat_id": "77009876543",
"caller_resolved": true,
"call_id": "00F8B01F0BC18EF2...",
"status": "offer",
"is_video": false,
"is_group": false,
"timestamp": 1781716572
}
}call_id (offer → ringing → terminate). Чтобы сценарий не сработал лишний раз:
- «Входящий звонок» (зазвонил) → берите только
status == "offer". - «Пропущенный / отклонённый» →
statusравенreject(вы отклонили) илиterminate(завершился сам).
caller/chat_id) или уведомить менеджера.Метка рекламы Click-to-WhatsApp
Если вы крутите рекламу Meta с кнопкой «Написать в WhatsApp», вместе с первым сообщением человека мы передаём вам метку клика — по ней рекламный кабинет Meta понимает, какое объявление привело покупателя.
Метка лежит в data.referral обычного события message. Отдельный адрес для неё настраивать не нужно — вебхук у номера один.
Поля внутри referral
Объект мы отдаём в том виде, в каком его присылает Meta, ничего не достраивая. Набор полей зависит от объявления: у видео-креатива приходит одно, у картинки другое. Обязательным не является ни одно поле — в наших данных из 1240 объектов у 58 не было даже ctwa_clid, хотя source_type был ad. Проверяйте наличие поля перед чтением; чаще всего приходят ctwa_clid и source_id.
| Поле | Описание |
|---|---|
ctwa_clid | Главное поле. Идентификатор клика по объявлению — именно его ждёт Meta Conversions API, когда вы отправляете ей продажу |
source_id | ID объявления, с которого пришёл человек |
source_type | ad — реклама, post — обычная публикация |
source_url | Ссылка на объявление или публикацию |
headline, body | Заголовок и текст объявления, как их видел человек |
media_type | image или video |
image_url, video_url, thumbnail_url | Ссылки на картинку, видео и превью креатива |
welcome_message | Заготовленный текст, который подставила кнопка объявления ({ "text": "…" }) |
Пример
{
"event": "message",
"instance": "+77001234567",
"api_key": "5ed944...",
"provider": "waba",
"data": {
"chat_id": "77009876543",
"sender": "77009876543",
"sender_name": "Руслан",
"message_id": "wamid.HBgL...",
"from_me": false,
"timestamp": 1788372604,
"message_type": "text",
"text": "Здравствуйте, интересует доставка",
"referral": {
"ctwa_clid": "AQAA...",
"source_id": "120212345678901234",
"source_type": "ad",
"source_url": "https://fb.me/...",
"headline": "Доставка за 30 минут",
"media_type": "image"
}
}
}- Метка бывает только на официальных номерах (WhatsApp Business API). На номере, подключённом по QR-коду, её не будет — Meta её туда не передаёт.
- Пришёл человек не с рекламы — поля
referralв событии просто нет. Само сообщение приходит как обычно. - Конверсии в Meta мы за вас не отправляем. Мы даём метку; отправка продажи в Conversions API — ваш шаг. Телефон Meta принимает только в виде SHA-256, хешируйте его у себя из поля
sender.
События сделок (вебхук)
Когда сделку завели или она переехала на другой этап, мы присылаем на ваш адрес событие deal — и сами подкладываем в него метку рекламы того человека. Связывать сделку с номером и выяснять, откуда пришёл клиент, вам не нужно: метку клика видим только мы.
Работает с двумя CRM: provider: "amocrm" и provider: "goflow" (CRM внутри GoFlow).
POST{ваш webhook URL}, поле event: "deal"
Как включить
- Галочка «События сделок» в кабинете: «Настройки → API и вебхуки», блок «Вебхук» (по умолчанию выключена).
- Там же выберите этапы, которые вам нужны — до пяти. Пока не выбран ни один этап, события о смене этапа не идут: мы не шлём поток, которого вы не просили.
- Нужно событие и на свежую сделку — включите отдельную галочку «Новый лид». Она к выбору этапов не привязана: лид может неделю висеть в «Неразобранном» и не сменить ни одного этапа. 🔴 Работает только с amoCRM — в CRM GoFlow сигнала о создании сделки нет, оттуда всё приходит как смена этапа.
- Для amoCRM нужна ещё подписка на события на стороне вашего аккаунта — её делаем мы, напишите в поддержку.
Поля внутри data
| Поле | Описание |
|---|---|
action | stage_changed — сделка сменила этап, lead_created — сделку только что завели. Второе бывает только у amoCRM: CRM GoFlow отдельного сигнала о создании сделки не даёт, и оттуда всё приходит как stage_changed |
seq | Сквозной номер события по этой сделке, с единицы. Нужен, чтобы увидеть пропуск: пришли 1, 2, 4 — третье не доехало. В редком случае сбоя на нашей стороне приедет null: событие при этом верное, просто без номера |
deal_id, deal_name | ID и название сделки в вашей CRM. Название может приехать пустым — у сделки его может не быть и в самой CRM |
phone | Телефон человека по сделке |
ctwa_clid, ad_source_id | Метка клика по рекламе и ID объявления. null, если человек пришёл не с рекламы |
stage, stage_id, old_stage_id | Этап: название, его ID и ID предыдущего этапа. old_stage_id приходит null у нового лида и всегда в CRM GoFlow — откуда сделка приехала, она не сообщает |
pipeline, pipeline_id | Воронка: название и ID |
status | open · won (успешно) · lost (отказ) |
amount, currency | Сумма сделки и валюта из настроек вашей компании (по умолчанию KZT): у сделки amoCRM своей валюты нет |
changed_at | Время события в формате unix |
attribution | Весь маркетинговый профиль лида одним плоским блоком, см. ниже |
meta_capi | Готовый кусок для отправки конверсии в ваш Facebook, см. ниже |
Пример
{
"event": "deal",
"instance": "+77001234567",
"api_key": "5ed944...",
"provider": "amocrm",
"data": {
"action": "stage_changed",
"seq": 3,
"deal_id": "36552269",
"deal_name": "Заявка с сайта",
"phone": "77009876543",
"ctwa_clid": "AQAA...",
"ad_source_id": "120212345678901234",
"stage": "Ждём оплаты",
"stage_id": "87138154",
"old_stage_id": "87138150",
"pipeline": "Продажи",
"pipeline_id": "11096386",
"status": "open",
"amount": 450000,
"currency": "KZT",
"changed_at": 1788740706,
"is_group": false,
"from_me": false,
"attribution": {
"ctwa_clid": "AQAA...",
"ad_source_id": "120212345678901234",
"utm_source": "tiktok",
"utm_medium": "cpc",
"utm_campaign": "zhalyuzi_astana",
"utm_id": "120251659317580123",
"from": "120251659317580123",
"ttclid": "E.C.P...",
"meta_fbc": "fb.1.1788...",
"first_message_hint": "tiktok",
"first_message_city": "Астана"
},
"meta_capi": {
"ctwa_clid": "AQAA...",
"whatsapp_business_account_id": "2968294326953602",
"event_time": 1788740706,
"action_source": "business_messaging",
"messaging_channel": "whatsapp",
"fbc": "fb.1.1788...",
"fbp": null,
"ad_id": "120251659317580123"
}
}
}Блок attribution
Весь маркетинговый профиль лида одним плоским списком: utm_source, utm_medium, utm_campaign, utm_content, utm_term, utm_id, utm_referrer, referrer, from, roistat, gclid, yclid, fbclid, gclientid, ym_uid, ym_counter, четыре openstat_*, ttclid, meta_fbc, meta_fbp, source_url, form, landing, ip, ip_location, ga_client_id, ym_client_id, google_gbraid, google_wbraid, ctwa_clid, ad_source_id, first_message_hint, first_message_city.
null. Схему таблицы у себя можно завести один раз и больше не менять: INSERT не сломается на лиде, пришедшем не с рекламы.ctwa_clid и ad_source_id (метка клика по рекламе) плюс first_message_hint и first_message_city (догадка по тексту, см. ниже). Остальные 32 приезжают из карточки сделки как есть.Подсказка по первому сообщению
first_message_hint и first_message_city — это ДОГАДКА по тексту первого сообщения человека («Пишу с TikTok, я из Астаны»), а не метка рекламы. Человек мог написать одно, а прийти с другого. Стройте на этом гипотезы, но не отчётность.Блок meta_capi
Готовый кусок для отправки конверсии в ваш Facebook своими руками: ctwa_clid, whatsapp_business_account_id, event_time, action_source, messaging_channel, fbc, fbp, ad_id. Отправьте его в Conversions API, ничего не пересобирая.
Телефона в нём нет: Meta принимает его только хешированным по SHA-256, и хешировать нужно у себя — из поля phone того же события.
Что важно знать заранее
- Истории не будет. События идут с момента включения; смены этапа, случившиеся раньше, задним числом не придут — такой истории нет ни у нас, ни в amoCRM.
- Доставка идёт темпом до 60 событий в минуту на компанию, очередь до 2000, событие старше 10 минут не отправляем. Массовый перенос сделок не завалит ваш сервер, но и не доедет мгновенно.
- Три попытки. Если ваш приёмник не ответил (сеть, таймаут, 5xx), повторим дважды; на
4xxповторять не будем. Дальше событие теряется — amoCRM свои события не повторяет. Пропуск виден поseq.
Доставка: повторы, дубли и сроки
Мы гарантируем доставку «хотя бы раз». Это значит, что одно и то же событие может прийти к вам дважды, и ваш сценарий обязан быть к этому готов.
- Дубли отсекайте по
data.message_id— он один и тот же у повторов. Это единственный надёжный ключ: время, текст и отправитель у двух разных сообщений могут совпасть, аmessage_id— нет. - Если ваш адрес не ответил, мы повторяем доставку: сначала трижды подряд в течение минуты, затем через 1, 5 и 30 минут и через 2 часа. Считается любой ответ
2xx; всё остальное — неудача. - Ответ
4xxповторов не вызывает. Такой код означает ошибку в вашем обработчике (не тот путь, не прошла авторизация), и повторять её бессмысленно. Починив приёмник, нажмите «Переотправить» в кабинете: «Настройки → API и вебхуки», блок «Вебхук». Кнопка появляется только когда недоставленные события действительно есть. - Недоставленное храним 7 дней. После этого переотправить его нечем.
- Порядок событий не гарантирован. Повторная доставка идёт в фоне, поэтому сообщение, ушедшее со второй попытки, может прийти позже следующего за ним. Ориентируйтесь на
data.timestamp, а не на порядок запросов. - Ссылка
media_urlможет заработать на несколько секунд позже самого события. Файл мы забираем у WhatsApp вторым шагом, уже после того, как отдали вам сообщение. Получили404 {"error":"media not ready, retry shortly"}— повторите через пару секунд. - Ссылка на файл живёт 7 дней с момента получения сообщения. Нужен файл дольше — скачайте и сохраните его у себя.
Номер отвалился (connection.update)
Официальный номер может перестать работать не по вашей вине, и молча: в переписке это выглядит как «клиенты перестали писать». Чтобы это было видно сразу, мы отправляем отдельное событие.
| Поле | Описание |
|---|---|
event | "connection.update" |
data.state | "close" — связи с номером нет, сообщения не идут. "open" — связь восстановлена |
data.reason | partner_removed — привязку сняли в приложении WhatsApp Business · inactivity — WhatsApp снял привязку сам: приложение на телефоне не открывали около двух недель · offboarded — номер отключён от GoFlow · app_uninstalled — из вашего аккаунта убрали приложение GoFlow · phone_removed — номер убрали из бизнес-аккаунта · account_deleted — удалён весь бизнес-аккаунт WhatsApp · restored — связь вернулась |
data.message | Готовая фраза для вашего оповещения — можно показывать как есть |
data.phone | Номер, о котором речь |
{
"event": "connection.update",
"provider": "waba",
"instance": "+77001234567",
"api_key": "5ed944...",
"data": {
"state": "close",
"reason": "inactivity",
"message": "WhatsApp снял привязку номера сам: приложение WhatsApp Business на телефоне не открывали около двух недель. Подключите номер заново в разделе «Интеграции».",
"phone": "+77001234567"
}
}История переписки одним файлом (history.ready)
При подключении официального номера WhatsApp отдаёт переписку за последние полгода — ту, что велась с телефона до подключения. Мы собираем её в один файл и присылаем событие со ссылкой. Отдельно запрашивать ничего не нужно.
history.ready для неё не будет.Событие
| Поле | Описание |
|---|---|
event | "history.ready" |
data.url | Ссылка на файл. Скачивается методом GET с тем же заголовком X-API-Key |
data.messages_count | Сколько сообщений в файле |
data.threads_count | Сколько собеседников |
data.media_count | Сколько вложений доступно по ссылке |
data.period | { from, to } — самое старое и самое свежее сообщение в файле |
data.expires_at | До какого момента файл доступен. Потом он удаляется вместе с вложениями |
{
"event": "history.ready",
"provider": "waba",
"instance": "+77001234567",
"api_key": "5ed944...",
"data": {
"history": true,
"phone": "+77001234567",
"url": "https://my.goflow.kz/api/webhook/history/export",
"messages_count": 4312,
"threads_count": 187,
"media_count": 54,
"period": { "from": "2026-03-25T09:14:00.000Z", "to": "2026-09-23T18:02:00.000Z" },
"expires_at": "2026-09-30T21:00:00.000Z",
"message": "Переписка за прошлый период готова: 4312 сообщений. Забрать файл можно в течение 7 дней."
}
}Что внутри файла
Те же самые события, что приходят вам на вебхук, сложенные в массив events и отсортированные по времени. Отдельного разбора не нужно: прогоните их тем же обработчиком, что и живые сообщения.
{
"history": true,
"format": "goflow-waba-events-v1",
"number": "+77001234567",
"generated_at": "2026-09-23T18:05:00.000Z",
"messages_count": 4312,
"threads_count": 187,
"media_count": 54,
"period": { "from": "2026-03-25T09:14:00.000Z", "to": "2026-09-23T18:02:00.000Z" },
"events": [
{
"event": "message",
"provider": "waba",
"instance": "+77001234567",
"data": {
"history": true,
"chat_id": "77009876543",
"sender": "77009876543",
"sender_name": "Айдана",
"from_me": false,
"message_id": "wamid.HBgL...",
"timestamp": 1774512840,
"message_type": "image",
"text": "Вот фото",
"media_url": "https://my.goflow.kz/api/webhook/history/media/wamid.HBgL...",
"mime_type": "image/jpeg"
}
}
]
}curl -s -H "X-API-Key: 5ed944..." \
"https://my.goflow.kz/api/webhook/history/export" \
-o history.json
# что есть и до какого числа — без скачивания самого файла
curl -s -H "X-API-Key: 5ed944..." https://my.goflow.kz/api/webhook/historyЧего в истории нет
data.history: trueстоит у каждого события. По нему отличайте перенос от живого сообщения: отвечать, слать уведомления и будить ботов на переписке полугодовой давности не нужно.- Вложения — только за последние две недели. Так отдаёт WhatsApp, и изменить это нельзя. У остальных сообщений вместо файла приходит текст «📎 Вложение не перенесено: файл старше 14 дней, WhatsApp его больше не отдаёт».
- Групповых чатов нет. WhatsApp не отдаёт их при этом способе подключения.
- Реакций, правок и удалений нет. Их не отдаёт WhatsApp.
is_forwardedиis_voiceв истории всегдаfalse, а цитат и меток рекламы нет: этих признаков WhatsApp в истории не передаёт. У живых сообщений они работают как обычно.- Файл и вложения живут 7 дней — столько же, сколько сама переписка у нас. После этого ссылки отвечают
410, и восстановить файл нечем: WhatsApp отдаёт историю только в первые сутки после подключения номера. - Поля
api_keyвнутри файла нет, в отличие от живых событий: файл вы уже скачали своим ключом, и дублировать его тысячами копий незачем. За вложениями ходите с тем же ключом в заголовке.
Скачивание файлов
В сообщениях с файлом приходит media_url вида https://my.goflow.kz/api/messages/media/<message_id>. Скачайте его методом GET с заголовком X-API-Key (ключ берётся из того же входящего — поле api_key):
curl -s -H "X-API-Key: 5ed944..." \
"https://my.goflow.kz/api/messages/media/2A52E6BE20A64E177479" \
-o file.bin- В ответ приходит сам файл. Для документов имя файла указано в заголовке
Content-Disposition(русские имена поддерживаются). - Крупные файлы (до ~50 МБ) скачиваются в фоне. Если дёрнуть ссылку слишком рано, придёт
404 {"error":"media not ready, retry shortly"}— повторите через пару секунд. - Файла больше нет →
410 {"error":"media_deleted"}. Срок хранения истёк: на тарифах, где мы переписку только передаём, вложения и сами сообщения удаляются через 7 дней. Повторять запрос бессмысленно. - Файл забрать не удалось →
410 {"error":"media_not_received"}. Скачать его у WhatsApp не получилось, и он уже не появится: само сообщение у вас есть, файла к нему не будет. Бывает редко. - Оба ответа
410— окончательные. Ответ404означает «ещё в пути»,410— «было и больше нет»; различайте их в своём сценарии, иначе он будет повторять запрос вечно. - Без ключа или с чужим ключом →
401.
Отправка сообщений
POSThttps://my.goflow.kz/api/messages с заголовком X-API-Key: <ключ номера>.
Ответ при успехе: { "ok": true, "message_id": "..." }
to — куда: номер 77009876543 (личка) или 120363...@g.us (группа). Берите его из chat_id входящего.
Текст
curl -X POST https://my.goflow.kz/api/messages \
-H "X-API-Key: 5ed944..." \
-H "Content-Type: application/json" \
-d '{ "to": "77009876543", "text": "Ваш заказ готов 👨🍳" }'Файл
media — это публичная ссылка на файл или строка base64.
curl -X POST https://my.goflow.kz/api/messages \
-H "X-API-Key: 5ed944..." \
-H "Content-Type: application/json" \
-d '{ "to": "77009876543",
"media": "https://site.kz/photo.jpg",
"mediatype": "image",
"caption": "Ваш чек" }'mediatype: image · video · audio · document.
С упоминанием (тег в группе)
Нужны оба поля: @номер в тексте и номер в mentioned:
curl -X POST https://my.goflow.kz/api/messages \
-H "X-API-Key: 5ed944..." \
-H "Content-Type: application/json" \
-d '{ "to": "120363000000000000@g.us",
"text": "@77009876543 готово",
"mentioned": ["77009876543"] }'mentioned — голые номера (мы сами добавим техническую часть адреса). @ в тексте вы ставите сами. Только @ в тексте без mentioned = просто текст, тег не сработает.Упомянуть всех (@all)
curl -X POST https://my.goflow.kz/api/messages \
-H "X-API-Key: 5ed944..." \
-H "Content-Type: application/json" \
-d '{ "to": "120363000000000000@g.us",
"text": "@all внимание",
"mentions_everyone": true }'Индикатор набора и отметка «прочитано»
Чтобы переписка выглядела по-человечески: отметить входящее прочитанным (синяя галочка) и показать «печатает…» перед ответом.
Печатает… (индикатор набора)
POSThttps://my.goflow.kz/api/messages/typing
curl -X POST https://my.goflow.kz/api/messages/typing \
-H "X-API-Key: 5ed944..." \
-H "Content-Type: application/json" \
-d '{ "to": "77009876543", "state": "on" }'state:"on"— показать набор (по умолчанию),"off"— убрать.- Один вызов держит индикатор около 5 секунд. Чтобы показывать дольше — вызовите ещё раз (повторяйте каждые ~5 сек нужное время, затем отправьте ответ).
{"ok":true} — наша часть выполнена. На iPhone обычно отображается нормально; на Android зависит от устройства — на некоторых марках может не показываться вовсе. Это поведение телефона получателя, не сбой.Отметить прочитанным (синяя галочка)
POSThttps://my.goflow.kz/api/messages/read
curl -X POST https://my.goflow.kz/api/messages/read \
-H "X-API-Key: 5ed944..." \
-H "Content-Type: application/json" \
-d '{ "to": "77009876543", "message_id": "3EB0..." }'to— этоchat_idиз входящего,message_id— id того сообщения, которое отмечаем.- Отмечает конкретное сообщение в момент вызова (а не всё подряд). Если хотите авто-чтение всех входящих — есть тумблер «Читать сообщения» в настройках номера, но только у номера, подключённого по QR-коду (шестерёнка на карточке в разделе «Мои номера»). Это настройка самого приложения WhatsApp на телефоне; у официального номера (WhatsApp Business API) её нет и быть не может.
{"ok":true} — мы отметили прочитанным; отображение синим — на стороне получателя, не сбой.Готовый сценарий: ответить, тегнув отправителя в группе
- Пришло входящее:
is_group:true,chat_id:"120363...@g.us",sender:"77007654321". - Отвечаете:
to = chat_id,text = "@77007654321 принял",mentioned = ["77007654321"]. - Номер для тега берите из
senderилиmentions— там всегда реальные телефоны.
curl -X POST https://my.goflow.kz/api/messages \
-H "X-API-Key: 5ed944..." \
-H "Content-Type: application/json" \
-d '{ "to": "120363000000000000@g.us",
"text": "@77007654321 принял в работу",
"mentioned": ["77007654321"] }'Частые вопросы
Можно ли один сценарий на несколько номеров?
Да. Повесьте один и тот же webhook URL на все номера. В каждом входящем будет instance (какой номер получил) и api_key (которым отвечать). Ничего вручную сопоставлять не нужно.
Приходят ли статусы «доставлено / прочитано»?
Нет, в вебхук они не отправляются. Галочки доставки видны в нашем кабинете в разделе «Чаты».
Как отключить сообщения из групп?
Официальный номер (WhatsApp Business API): ничего включать не нужно — групповых сообщений по этому пути не приходит вовсе, Meta их не передаёт.
Номер по QR-коду: в настройках номера (шестерёнка на карточке в разделе «Мои номера») включите тумблер «Игнорировать группы» — тогда групповые сообщения вообще не будут приходить на ваш URL.
Как понять, из какого объявления пришёл лид?
Если человек нажал «Написать в WhatsApp» под рекламой Meta, в первом его сообщении придёт блок referral с ctwa_clid и ID объявления — см. раздел «Метка рекламы». Хотите видеть ещё и продажу по этому лиду — включите «События сделок»: метку мы подложим в событие сами.
Придут ли события по сделкам, которые двигали раньше?
Нет. События идут с момента, когда вы включили галочку. Истории смен этапа не существует ни у нас, ни в amoCRM, поэтому задним числом прислать нечего.
Что в поле raw?
Несколько вспомогательных полей сообщения: text, type, timestamp и quoted (если это ответ на сообщение — его текст, отправитель и id). Всё это есть и в data, так что для большинства задач достаточно data.
Будут ли готовые ноды для n8n?
Да, в планах — готовые ноды «приём входящих» и «отправка», чтобы не настраивать HTTP вручную. Пока используйте обычные HTTP-узлы по этой документации.