WhatsApp → Telegram: входящие в рабочий чат и ответ реплаем
Обновлено
Клиенты пишут в WhatsApp, а команда живёт в Telegram. Вместо того чтобы передавать телефон с рабочим номером из рук в руки, можно пересылать каждое входящее в общий чат Telegram и отвечать клиенту реплаем — ответ уйдёт в WhatsApp с номера компании.
Страница для небольших команд — магазинов, служб доставки, сервисов, — которым нужен простой общий «почтовый ящик» для WhatsApp без CRM. Понадобится Telegram-бот и небольшой сервер на Node.js.
- Менеджер отвечает реплаем в Telegram
- ваш бот
- POST /messages/send
- клиент в WhatsApp
- Клиент пишет в WhatsApp
- вебхук wapi.kz
- ваш бот
- сообщение в рабочем чате Telegram
Что можно автоматизировать
- Входящие в общий чат. Каждое сообщение клиента появляется в группе Telegram с телефоном и номером, на который он написал.
- Ответ реплаем. Менеджер отвечает на пересланное сообщение — бот отправляет текст клиенту в WhatsApp и подтверждает отправку.
- Несколько номеров — разные чаты. Номер продаж пишет в чат продаж, номер сервиса — в чат сервиса. Подробнее — в гайде о нескольких номерах.
- Ответили с телефона. Если кто-то ответил клиенту прямо с телефона (событие
message.out), бот показывает это в чате, чтобы никто не ответил второй раз. - Номер отключился. Событие
session.statusсо статусомFAILEDилиSTOPPED— тревога в чат: пора переподключить по QR. - Баланс на исходе. Раз в день бот проверяет
GET /balanceи пишет в чат, еслиdays_leftменьше трёх.
Как это устроено
Со стороны Telegram: бот получает обновления через вебхук (setWebhook с параметром secret_token — Telegram пришлёт его в заголовке X-Telegram-Bot-Api-Secret-Token) и пишет в чат методом sendMessage с chat_id и text. В группе бот в режиме приватности всё равно получает ответы на свои сообщения — для реплаев этого достаточно.
Со стороны wapi.kz — вебхук номера с событием message (документация) и POST /messages/send для ответа (документация).
Как бот понимает, кому отвечать: в первой строке пересланного сообщения он пишет телефон клиента и id номера. Когда менеджер отвечает реплаем, бот читает эту строку из цитаты. База данных не нужна, и после перезапуска сервера ответы на старые сообщения тоже работают.
Настройка по шагам
- Подключите номер в wapi.kz (как подключить) и возьмите ключ в разделе «API и MCP».
- Создайте бота у @BotFather, получите токен, добавьте бота в рабочую группу и узнайте
chat_idгруппы. - Разверните код ниже на сервере с публичным https-адресом, задайте переменные окружения.
- Укажите Telegram адрес бота: вызовите
setWebhookсurl=https://ваш-сервер.kz/tgи своимsecret_token. - В кабинете wapi.kz задайте вебхук номера
https://ваш-сервер.kz/wapi?token=СЕКРЕТ. - Напишите на номер с другого телефона, ответьте реплаем в группе и проверьте, что ответ пришёл в WhatsApp.
Пример кода
Node.js 18+ и Express. Первый маршрут пересылает в Telegram входящие, ответы с телефона и отключение номера, второй — отправляет реплаи клиенту.
const express = require("express");
const app = express();
app.use(express.json());
const TG = `https://api.telegram.org/bot${process.env.TG_TOKEN}`;
const CHAT = process.env.TG_CHAT_ID; // id рабочей группы, например -1001234567890
const tg = (method, body) =>
fetch(`${TG}/${method}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
// 1. WhatsApp → Telegram
app.post("/wapi", (req, res) => {
if (req.query.token !== process.env.WAPI_HOOK_TOKEN) return res.sendStatus(403);
res.sendStatus(200); // ответить сразу, обработать — после
const e = req.body;
let text;
if (e.event === "message" && e.payload.from.endsWith("@c.us")) { // только личные чаты с телефоном
const body = e.payload.hasMedia ? "[фото или файл — откройте чат на телефоне]" : e.payload.body;
text = `WhatsApp ${e.payload.from.split("@")[0]} · номер ${e.wapi.number_id}\n\n${body}`;
} else if (e.event === "message.out") {
text = `С телефона ответили ${String(e.payload.from).split("@")[0]}: ${e.payload.body}`; // чат — всегда в from
} else if (e.event === "session.status" && ["FAILED", "STOPPED"].includes(e.payload.status)) {
text = `Номер ${e.wapi.phone} отключился (${e.payload.status}) — переподключите в кабинете`;
}
if (text) tg("sendMessage", { chat_id: CHAT, text }).catch(console.error);
});
// 2. Реплай в Telegram → WhatsApp
app.post("/tg", async (req, res) => {
if (req.get("X-Telegram-Bot-Api-Secret-Token") !== process.env.TG_SECRET) return res.sendStatus(403);
res.sendStatus(200);
const msg = req.body.message;
const head = msg?.reply_to_message?.text?.match(/^WhatsApp (\d{10,15}) · номер (\d+)/);
if (!head || !msg.text || String(msg.chat.id) !== CHAT) return;
try {
const r = await fetch("https://wapi.kz/api/v1/messages/send", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.WAPI_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ to: head[1], text: msg.text, from: Number(head[2]) }),
});
const data = await r.json();
await tg("sendMessage", {
chat_id: CHAT,
reply_parameters: { message_id: msg.message_id },
text: r.ok ? "Отправлено в WhatsApp" : `Не отправлено: ${data.code} — ${data.error}`,
});
} catch (err) {
console.error(err);
}
});
app.listen(3000);Здесь ключ аккаунта: бот отвечает с того номера, на который написал клиент, — его id берётся из пересланного сообщения и уходит в поле from.
Ограничения
- Это не операторский чат: нет назначения ответственного, статусов обращений и поиска по истории, как в helpdesk или CRM. Для небольшой команды этого обычно хватает.
- Фото и документы от клиентов бот из примера не пересылает — в событии
hasMedia: true, и бот пишет об этом в чат. Сам файл сохраняется у нас и доступен по ссылкеmedia.urlвGET /messages/{id}: бот может скачать его и отправить в Telegram. - Сообщения клиентов окажутся на серверах Telegram. Если для вас важна локализация персональных данных, учтите это — подробнее в гайде о хранении ПД в Казахстане.
- Вебхуки wapi.kz не повторяются: если сервер бота лежал, пропущенное заберите через
GET /messages?since=…(история). - Лимит — 1 сообщение в секунду с номера (лимиты). Ответы тем, кто написал сам, не расходуют лимит первых сообщений новым людям.
Не хотите поднимать бота сами? Зарегистрируйтесь, подключите номер и оставьте заявку из кабинета — поможем с настройкой. Номер — 9 900 ₸ в месяц, сообщения и вебхуки бесплатны (цены).
Частые вопросы
Увидит ли клиент, что ему ответили из Telegram?
Нет. Для клиента это обычное сообщение с вашего номера WhatsApp. В истории wapi.kz оно будет с source: "api".
Можно ли собрать это без своего сервера?
Что, если два менеджера ответят одновременно?
Клиент получит оба ответа. Договоритесь в команде: кто первым поставил реакцию на сообщение, тот и отвечает.
Можно ли так отвечать в группы WhatsApp?
Нет, отправка в группы через API недоступна — только личные чаты. Поэтому бот пропускает сообщения из групп.
Подключите WhatsApp к Telegram
9 900 ₸ в месяц за номер, без платы за сообщения. Сервер в Казахстане, оплата Kaspi или счётом на ТОО/ИП. Подключение — около 5 минут.