Перейти к содержимому

outgoingMessageStatus

Обновлено 17 октября 2026

Сообщение номера канала отправлено, доставлено, прочитано или не дошло. Статусы приходят и для сообщений через 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 да нет да неизвестный исход
WhatsApp да да да неизвестный исход
Почта да нет отчёт о прочтении, если получатель его отправил неизвестный исход; недоставка — отчёт почтового сервера

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"))

Что дальше

Была ли статья полезна?