Сообщение номера канала отправлено, доставлено, прочитано или не дошло. Статусы приходят и для сообщений через API, и для сообщений с телефона.
typeWebhook |
outgoingMessageStatus |
typeMessage |
— |
| Флаг настроек | outgoingWebhook |
| Каналы | MAX, Telegram, WhatsApp, почта |
Пример
Мария прочитала сообщение, которое приложение отправило в MAX:
{
"typeWebhook": "outgoingMessageStatus",
"chatId": "8695836",
"instanceData": {"idInstance": 7100000001, "wid": "79990000001@c.us", "typeInstance": "v3", "channel": "max"},
"timestamp": 1791823705,
"idMessage": "117428956522361912",
"status": "read",
"sendByApi": true
}
Поля
| Поле | Описание |
|---|---|
chatId |
чат, куда ушло сообщение |
idMessage |
id отправленного сообщения — тот же, что в ответе метода отправки |
status |
sent, delivered, read или failed |
sendByApi |
true — сообщение отправлено через API, false — с телефона |
description |
причина — только у failed |
clientMessageId |
ваш ключ отправки — только у failed после неизвестного исхода |
У статуса нет senderData, messageData и eventId. Ключ от повторной обработки — пара idMessage + status.
Значения status
status |
Что значит |
|---|---|
sent |
площадка приняла сообщение. Приходит сразу после отправки через API |
delivered |
сообщение получил телефон собеседника |
read |
собеседник прочитал; в группе — хотя бы один участник; голосовое в WhatsApp — прослушано |
failed |
сообщение не дошло — причина в description |
Статус только растёт: sent → delivered → read. Опоздавшее «доставлено» после «прочитано» не приходит. failed может прийти и после sent.
По каналам
| Канал | sent |
delivered |
read |
failed |
|---|---|---|---|---|
| MAX | да | нет | да | неизвестный исход |
| Telegram | да | нет | да | неизвестный исход |
| да | да | да | неизвестный исход | |
| Почта | да | нет | отчёт о прочтении, если получатель его отправил | неизвестный исход; недоставка — отчёт почтового сервера |
sent приходит только для сообщений через API. Для сообщений с телефона приходят delivered и read с sendByApi: false.
В MAX и Telegram «прочитано» приходит отметкой «прочитано всё до»: Gratio присылает read по каждому вашему сообщению в чате до неё. Если сообщения прочитали, пока канал был не на связи, Telegram сообщит об этом при подключении.
failed после неизвестного исхода
Отправка ответила 503 outcome_unknown: связь оборвалась посреди отправки. Gratio сам ищет сообщение в истории чата. Нашёл — приходят outgoingAPIMessageReceived (см. Свои сообщения) и sent. Не нашёл за 10 минут — failed:
{
"typeWebhook": "outgoingMessageStatus",
"chatId": "8695836",
"instanceData": {"idInstance": 7100000001, "wid": "79990000001@c.us", "typeInstance": "v3", "channel": "max"},
"timestamp": 1791824300,
"idMessage": "",
"status": "failed",
"sendByApi": true,
"description": "отправка не подтверждена площадкой",
"clientMessageId": "booking-1532-confirm"
}
idMessage пустой: сообщения нет. Связать статус с запросом можно по clientMessageId — он есть, если вы передали его в методе отправки. Подробно — Надёжная отправка без дублей.
Недоставка письма
Почтовый сервер вернул отчёт о недоставке:
{
"typeWebhook": "outgoingMessageStatus",
"chatId": "maria@client.ru",
"instanceData": {"idInstance": 7100000001, "wid": "info@school.ru", "typeInstance": "email", "channel": "email"},
"timestamp": 1791824410,
"idMessage": "c62b698304229a98aad3",
"status": "failed",
"sendByApi": true,
"description": "550 5.1.1 User unknown"
}
description — причина из отчёта сервера. Отчёт без причины — «Письмо не доставлено». Подробно о письмах — Письмо.
Как обработать
Обновлять статус сообщения в своей системе и не откатывать его назад:
RANK = {"sent": 1, "delivered": 2, "read": 3, "failed": 4}
def on_status(body: dict) -> None:
if body["typeWebhook"] != "outgoingMessageStatus":
return
status = body["status"]
if status == "failed" and not body["idMessage"]:
mark_failed_by_key(body.get("clientMessageId"), body.get("description", ""))
return
current = get_status(body["idMessage"]) # ваша таблица отправленных
if current is None or RANK[status] > RANK[current]:
set_status(body["idMessage"], status, reason=body.get("description"))
Что дальше
- Свои сообщения — уведомление о самом отправленном сообщении.
- Надёжная отправка без дублей —
clientMessageIdиoutcome_unknown. - sendMessage — отправить сообщение.
