my.goflow WhatsApp API ← В кабинет

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 (телефон).
💡 Один и тот же webhook URL можно повесить на несколько номеров. Различайте их по полю instance (это номер-получатель), а отвечайте ключом api_key из того же входящего — настраивать ничего не придётся.

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

  1. Подключите номер. Официальный (WhatsApp Business API) — в разделе «Интеграции», обычный — по QR-коду в разделе «Мои номера». Вебхук работает одинаково на обоих.
  2. Включите модуль «Вебхук / API» (без него раздел с ключом скрыт).
  3. Откройте в кабинете «Настройки → API и вебхуки», выберите номер в списке сверху и заполните блок «Вебхук»:
    • Включить webhook — отправлять ли события на ваш адрес.
    • URL — куда мы шлём входящие, например https://your-n8n.com/webhook/abc.
    • Входящие сообщения — получать ли их в вебхук (если выключить, придут только служебные события вроде подключения).
    • Звонки — получать ли события входящих звонков (по умолчанию выключено; см. раздел «Входящий звонок»).
    • Только лиды с рекламы — присылать не всю переписку, а только сообщения с меткой рекламы Meta. Есть у официальных номеров. 🔴 Метка приходит лишь с первым сообщением человека, поэтому его следующие сообщения в вебхук не поедут (см. раздел «Метка рекламы»).
    • События сделок — присылать событие, когда сделку завели или она сменила этап (по умолчанию выключено, включаем по запросу). Там же выбираются этапы, которые вам нужны, и отдельная галочка «Новый лид» (см. раздел «События сделок»).

    Настройки относятся к выбранному номеру. Нажмите «Сохранить настройки вебхука» — они применяются сразу.

  4. 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@alltrue — упомянули всех в группе
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 объявления, его заголовок и ссылка. Приходит только с первым сообщением человека после клика — см. раздел «Метка рекламы»

Примеры

Текстовое сообщение (личка):

JSON
{
  "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": "Здравствуйте, заказ готов?"
  }
}

Сообщение в группе с упоминанием:

JSON
{
  "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.

Картинка с подписью:

JSON
{
  "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".

Реакция на сообщение:

JSON
{
  "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.

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

JSON
{
  "event": "connection",
  "instance": "+77001234567",
  "api_key": "...",
  "data": { "state": "connected" }
}

Входящий звонок (вебхук)

Если в разделе «API и вебхуки» у номера включён тумблер «Звонки» (по умолчанию выключен), при входящем звонке на ваш URL приходит событие:

POST{ваш webhook URL}, поле event: "call"

Поля внутри data

ПолеОписание
callerКто звонит — номер звонящего, напр. 77009876543. Дублируется в chat_id, чтобы можно было сразу написать в ответ
caller_resolvedtrue — в caller реальный телефон. false — WhatsApp скрыл номер и восстановить не удалось (в caller технический ID)
caller_lidТехнический ID звонящего (когда WhatsApp прислал звонок в скрытом виде). Для трассировки; обычно номер уже восстановлен в caller
call_idID звонка — один на весь звонок. По нему отсеивайте повторные события (см. ниже)
statusСтадия: offer (зазвонил) → ringing → reject / terminate (завершился)
is_videotrue — видеозвонок
is_grouptrue — групповой звонок
timestampВремя в формате unix

Пример

JSON
{
  "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 (завершился сам).
📞 Принять звонок голосом через API нельзя (WhatsApp не отдаёт аудиопоток). Типичный сценарий — поймать звонок и написать звонящему (его номер уже в 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_idID объявления, с которого пришёл человек
source_typead — реклама, post — обычная публикация
source_urlСсылка на объявление или публикацию
headline, bodyЗаголовок и текст объявления, как их видел человек
media_typeimage или video
image_url, video_url, thumbnail_urlСсылки на картинку, видео и превью креатива
welcome_messageЗаготовленный текст, который подставила кнопка объявления ({ "text": "…" })

Пример

JSON
{
  "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"
    }
  }
}
💰 Реклама даёт неделю: бесплатную, а сейчас ещё и с обычным текстом. Переписка с тем, кто пришёл по клику с объявления, может быть бесплатной до 7 дней: окно открывается, только если вы ответили ему в первые сутки и Meta пометила этот ответ как бесплатный (человеку, написавшему с компьютера, она окно не открывает; ответ с телефона из приложения WhatsApp Business, по документации Meta, тоже не открывает). Отсчёт идёт от вашего ответа. Не ответили за сутки, и окно не открылось вовсе. Пока эта неделя идёт, Meta сейчас пропускает и обычный текст, даже если человек молчит больше суток, и кабинет GoFlow даёт так писать до конца недели. В остальных диалогах обычный текст можно 24 часа с последнего сообщения человека, дальше только шаблон. Правило про текст внутри недели Meta прямо не закрепила: если она его отменит, после суток молчания снова понадобится шаблон.
⚙️ В кабинете, раздел «Настройки → API и вебхуки», блок «Вебхук», есть галочка «Только лиды с рекламы»: с ней на ваш адрес поедут лишь сообщения с меткой, а не вся переписка. 🔴 Учтите главное: метка приходит только с первым сообщением человека, поэтому его второе и следующие сообщения в вебхук уже не поедут. Включайте, если вам нужен сам факт рекламного обращения, а не диалог целиком. Галочка есть только у официальных номеров.
  • Метка бывает только на официальных номерах (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"

Как включить

  1. Галочка «События сделок» в кабинете: «Настройки → API и вебхуки», блок «Вебхук» (по умолчанию выключена).
  2. Там же выберите этапы, которые вам нужны — до пяти. Пока не выбран ни один этап, события о смене этапа не идут: мы не шлём поток, которого вы не просили.
  3. Нужно событие и на свежую сделку — включите отдельную галочку «Новый лид». Она к выбору этапов не привязана: лид может неделю висеть в «Неразобранном» и не сменить ни одного этапа. 🔴 Работает только с amoCRM — в CRM GoFlow сигнала о создании сделки нет, оттуда всё приходит как смена этапа.
  4. Для amoCRM нужна ещё подписка на события на стороне вашего аккаунта — её делаем мы, напишите в поддержку.

Поля внутри data

ПолеОписание
actionstage_changed — сделка сменила этап, lead_created — сделку только что завели. Второе бывает только у amoCRM: CRM GoFlow отдельного сигнала о создании сделки не даёт, и оттуда всё приходит как stage_changed
seqСквозной номер события по этой сделке, с единицы. Нужен, чтобы увидеть пропуск: пришли 1, 2, 4 — третье не доехало. В редком случае сбоя на нашей стороне приедет null: событие при этом верное, просто без номера
deal_id, deal_nameID и название сделки в вашей 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
statusopen · won (успешно) · lost (отказ)
amount, currencyСумма сделки и валюта из настроек вашей компании (по умолчанию KZT): у сделки amoCRM своей валюты нет
changed_atВремя события в формате unix
attributionВесь маркетинговый профиль лида одним плоским блоком, см. ниже
meta_capiГотовый кусок для отправки конверсии в ваш Facebook, см. ниже
📌 Тело всегда полное, а не разница с прошлым разом. Пропустили событие — следующее всё равно описывает сделку целиком. Если сделка за пару секунд прошла два выбранных этапа, придут два события, по одному на каждый.

Пример

JSON
{
  "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.

🔑 Ключей всегда 36, и они всегда одни и те же. Чего у лида нет — приезжает как null. Схему таблицы у себя можно завести один раз и больше не менять: INSERT не сломается на лиде, пришедшем не с рекламы.
⚠️ Этот блок мы пересылаем, а не добываем. Он заполнен ровно настолько, насколько его заполняет ваш сайт: нет формы, которая пишет utm-метки в сделку — блок придёт пустым, и это не сбой у нас. Наших полей в нём четыре: 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.reasonpartner_removed — привязку сняли в приложении WhatsApp Business · inactivity — WhatsApp снял привязку сам: приложение на телефоне не открывали около двух недель · offboarded — номер отключён от GoFlow · app_uninstalled — из вашего аккаунта убрали приложение GoFlow · phone_removed — номер убрали из бизнес-аккаунта · account_deleted — удалён весь бизнес-аккаунт WhatsApp · restored — связь вернулась
data.messageГотовая фраза для вашего оповещения — можно показывать как есть
data.phoneНомер, о котором речь
JSON
{
  "event": "connection.update",
  "provider": "waba",
  "instance": "+77001234567",
  "api_key": "5ed944...",
  "data": {
    "state": "close",
    "reason": "inactivity",
    "message": "WhatsApp снял привязку номера сам: приложение WhatsApp Business на телефоне не открывали около двух недель. Подключите номер заново в разделе «Интеграции».",
    "phone": "+77001234567"
  }
}
🔴 Ни одна из этих причин не является блокировкой: аккаунт WhatsApp цел, апелляцию подавать не нужно. Номер возвращается в работу одним действием — подключить его заново в разделе «Интеграции». Событие приходит не чаще одного раза в час на одно и то же состояние: WhatsApp повторяет свои уведомления часами, и мы эти повторы гасим.

История переписки одним файлом (history.ready)

При подключении официального номера WhatsApp отдаёт переписку за последние полгода — ту, что велась с телефона до подключения. Мы собираем её в один файл и присылаем событие со ссылкой. Отдельно запрашивать ничего не нужно.

Это про номера, переписку которых мы вам только передаём и у себя не храним. Если вы пользуетесь чатами GoFlow, история переносится прямо в них — кнопкой «Показать в чатах» в разделе «Чаты», и события 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До какого момента файл доступен. Потом он удаляется вместе с вложениями
JSON
{
  "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 и отсортированные по времени. Отдельного разбора не нужно: прогоните их тем же обработчиком, что и живые сообщения.

JSON
{
  "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
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 внутри файла нет, в отличие от живых событий: файл вы уже скачали своим ключом, и дублировать его тысячами копий незачем. За вложениями ходите с тем же ключом в заголовке.
Файл можно скачать и руками: «Настройки → API и вебхуки», блок «Вебхук», строка «Переписка за прошлый период». Она появляется, только когда файл действительно есть.

Скачивание файлов

В сообщениях с файлом приходит media_url вида https://my.goflow.kz/api/messages/media/<message_id>. Скачайте его методом GET с заголовком X-API-Key (ключ берётся из того же входящего — поле api_key):

cURL
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
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
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
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
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
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 сек нужное время, затем отправьте ответ).
ℹ️ «Печатает…» — эфемерный сигнал WhatsApp. Если ответ {"ok":true} — наша часть выполнена. На iPhone обычно отображается нормально; на Android зависит от устройства — на некоторых марках может не показываться вовсе. Это поведение телефона получателя, не сбой.

Отметить прочитанным (синяя галочка)

POSThttps://my.goflow.kz/api/messages/read

cURL
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) её нет и быть не может.
ℹ️ Синяя галочка зависит от стороны получателя: если у него выключены «Отчёты о прочтении» — не посинеет, и может не посинеть даже при включённых или на некоторых Android (телефон/синхронизация). Если ответ {"ok":true} — мы отметили прочитанным; отображение синим — на стороне получателя, не сбой.
⏱️ Чтобы было похоже на живого оператора, добавляйте небольшую паузу (например, случайную) перед отметкой и перед набором: пришло → пауза → прочитано → пауза → печатает… → ответ.

Готовый сценарий: ответить, тегнув отправителя в группе

  1. Пришло входящее: is_group:true, chat_id:"120363...@g.us", sender:"77007654321".
  2. Отвечаете: to = chat_id, text = "@77007654321 принял", mentioned = ["77007654321"].
  3. Номер для тега берите из sender или mentions — там всегда реальные телефоны.
cURL
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-узлы по этой документации.