В этом шаге Gratio начнёт присылать уведомления на ваш адрес сам — опрашивать очередь не нужно.
Что понадобится
- переменные
GRATIO_URL,GRATIO_ID,GRATIO_TOKENиз Шаг 2. Первый запрос; - Python 3.10+ (
pip install fastapi uvicorn) или Node.js 18+ (npm install express); - публичный HTTPS-адрес, который ведёт на ваш обработчик. На своём компьютере подойдёт любой сервис туннелей, который выдаёт публичный HTTPS-адрес для локального порта.
Как работает вебхук
Gratio Ваш сервер
│ POST /gratio/hook {уведомление} ──────►│ проверить токен
│ │ сохранить, ответить сразу
│◄──────────────────────────── 200 OK ────│
│ │ обработать в фоне
│ POST /gratio/hook {следующее} ────────►│
│ │
│ нет ответа или не 2xx: │
│ повтор через 1, 5, 15, 60, 300 с … │
1. Запустите обработчик
Придумайте секрет — длинную случайную строку — и сохраните в GRATIO_HOOK_TOKEN. Gratio будет присылать его в заголовке Authorization.
Python
Файл hook.py, запуск — uvicorn hook:app --port 8080:
import os
from fastapi import BackgroundTasks, FastAPI, Header, HTTPException
app = FastAPI()
HOOK_TOKEN = os.environ["GRATIO_HOOK_TOKEN"]
def process(body: dict) -> None:
print(body["typeWebhook"], body.get("senderData", {}).get("chatId"), body.get("messageData"))
@app.post("/gratio/hook")
async def hook(body: dict, tasks: BackgroundTasks, authorization: str = Header("")):
if authorization != f"Bearer {HOOK_TOKEN}":
raise HTTPException(status_code=401)
tasks.add_task(process, body)
return {"ok": True}
Node.js
Файл hook.mjs, запуск — node hook.mjs:
import express from "express";
const app = express();
app.use(express.json({ limit: "1mb" }));
app.post("/gratio/hook", (req, res) => {
if (req.get("authorization") !== `Bearer ${process.env.GRATIO_HOOK_TOKEN}`) {
return res.sendStatus(401);
}
res.sendStatus(200);
const body = req.body;
console.log(body.typeWebhook, body.senderData?.chatId, body.messageData);
});
app.listen(8080);
Вы увидите: сервер слушает порт 8080.
2. Откройте публичный адрес
Направьте туннель на порт 8080 или разместите обработчик на сервере с HTTPS. Адрес обработчика — например, https://example.ru/gratio/hook.
Адрес должен быть публичным: внутренние и локальные адреса Gratio не принимает (400 bad_url).
3. Укажите адрес в настройках канала
Метод setSettings: адрес вебхука и ваш секрет. Замените адрес и секрет на свои:
curl
curl -X POST "$GRATIO_URL/waInstance$GRATIO_ID/setSettings/$GRATIO_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"webhookUrl": "https://example.ru/gratio/hook",
"webhookUrlToken": "s3cr3t-hook-token"
}'
Python
import os
import requests
BASE = f"{os.environ['GRATIO_URL']}/waInstance{os.environ['GRATIO_ID']}"
TOKEN = os.environ["GRATIO_TOKEN"]
url = f"{BASE}/setSettings/{TOKEN}"
payload = {
"webhookUrl": "https://example.ru/gratio/hook",
"webhookUrlToken": "s3cr3t-hook-token",
}
response = requests.post(url, json=payload, timeout=60)
print(response.status_code, response.json())
Node.js
const { GRATIO_URL, GRATIO_ID, GRATIO_TOKEN } = process.env;
const base = `${GRATIO_URL}/waInstance${GRATIO_ID}`;
const url = `${base}/setSettings/${GRATIO_TOKEN}`;
const payload = {
webhookUrl: "https://example.ru/gratio/hook",
webhookUrlToken: "s3cr3t-hook-token",
};
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
console.log(response.status, await response.json());
PHP
<?php
$base = getenv('GRATIO_URL') . '/waInstance' . getenv('GRATIO_ID');
$url = $base . '/setSettings/' . getenv('GRATIO_TOKEN');
$payload = [
'webhookUrl' => 'https://example.ru/gratio/hook',
'webhookUrlToken' => 's3cr3t-hook-token',
];
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$response = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), PHP_EOL;
print_r($response);
Вы увидите: {"saveSettings": true}.
4. Проверьте
Напишите на подключённый номер с телефона.
Вы увидите в консоли обработчика:
incomingMessageReceived 8695836 {'typeMessage': 'textMessage', 'textMessageData': {'textMessage': 'Здравствуйте!'}}
Пока задан вебхук, receiveNotification отвечает 400 webhook_set — у канала одна очередь, и её читает вебхук. Вернуться к очереди — setSettings с "webhookUrl": "".
Правила для обработчика
- Отвечайте сразу, обработку делайте в фоне: Gratio ждёт ответа 30 секунд.
- Проверяйте секрет в
Authorization. - Отсекайте повторы по
eventId: если ответ потерялся, уведомление придёт снова. - Не обрабатываете уведомление — всё равно ответьте
200, иначе очередь встанет на нём.
Подробно — в статье Вебхук.
Что дальше
Канал подключён, сообщения уходят и приходят. Выберите сценарий:
Чат-бот на PythonБот, который отвечает клиентам в MAX, Telegram или WhatsApp по меню, присылает файл и зовёт оператора, — на очереди уведомлений, без публичного сервера. Переписка в своей CRMВстроить чаты MAX, Telegram и WhatsApp в свою CRM — входящие в карточку, ответ оператора, статусы, сообщения с телефона, правки, история и разрыв истории. Напоминания и рассылки без блокировокСкрипт напоминаний клиентам — выбор канала по номеру, рабочие часы, темп, правила WhatsApp, отложенные повторы и защита от дублей.Или изучите основы: Как проходят сообщения и уведомления, Темп и лимиты, Ответы и ошибки.
