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

Ответы и ошибки

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

Формат

Успех — 200 и JSON. Ошибка — JSON с текстом и кодом:

{"message": "Текст длиннее 4000 символов", "code": "text_too_long"}

Если запрос можно повторить позже, в ответе есть retryAfter (секунды) и заголовок Retry-After:

{"message": "Создавать группы можно не чаще раза в 5 минут", "code": "too_frequent", "retryAfter": 214}

Опирайтесь на code: текст message написан для человека и может меняться.

Коды

HTTP code Что случилось Что делать
400 validation нет обязательного поля, неверный тип, неверный JSON, адрес чата или idMessage не этого канала исправить запрос
400 not_authorized канал не подключён к мессенджеру проверить getStateInstance, привязать номер в кабинете
400 no_account на номере нет аккаунта в этом мессенджере —
400 bad_phone номер не из 11–12 цифр исправить номер
400 bad_url ссылка не http(s) или ведёт во внутреннюю сеть дать публичную ссылку
400 url_unavailable файл по ссылке не скачался проверить ссылку
400 file_empty, upload_failed файл пустой или площадка его не приняла —
413 — тело запроса больше 100 МБ — отклонено до обработки уменьшить файл
400 text_too_long текст длиннее предела канала разбить текст
400 webhook_set receiveNotification, когда у канала задан вебхук читать вебхук или снять его
400 код площадки (chat.not.found, privacy_restricted…) площадка отказала в действии см. message
401 — неверный idInstance или токен; ключ перевыпущен или отозван взять ключ в кабинете
402 payment_required канал на паузе за неоплату, закрыта отправка продлить канал в кабинете
403 reserved попытка изменить системную подписку Gratio —
404 — неизвестный метод проверить имя метода
409 idempotency_conflict clientMessageId уже использован для другого содержимого новый ключ для нового сообщения
409 busy на канале уже идёт разговор через API дождаться конца звонка
409 limit у канала уже 5 подписок удалить ненужную
429 too_frequent и другие темп канала: залп сверх правил площадки повторить после Retry-After
429 — больше 30 запросов в секунду с одного адреса снизить частоту
469 rate_limited мессенджер ограничил поиск номеров или вступления повторить после Retry-After
500 internal сбой Gratio повторить позже; с clientMessageId повтор безопасен
500 too_large тело JSON больше 100 КБ уменьшить тело, файлы — через uploadFile
501 not_supported канал этого не умеет getCapabilities, см. Возможности каналов
503 unavailable канал сейчас не обслуживается, сообщение площадке не отправлялось повторить после Retry-After
503 outcome_unknown связь оборвалась посреди отправки, дошло ли сообщение — неизвестно повторить с тем же clientMessageId

Отказ с паузой всегда приходит как 429 или 469 с Retry-After. Отказ, который повтор не исправит, — как 400 с причиной в code.

Свои коды есть у отдельных методов и каналов — они описаны в статьях WhatsApp, Поиск и вступление: правила и лимиты, Звонки: как это работает и sendEmail.

Групповые методы

Методы групп, как у Green API, на отказ площадки отвечают 200 с флагом false и причиной:

{"addParticipant": false, "reason": "privacy_restricted: пользователь запретил приглашения"}

Проверяйте флаг в ответе, а не только код HTTP.

Когда повторять

Ответ Повторять?
429, 469, 503 unavailable да, после Retry-After
500 internal, сетевой сбой, тайм-аут да, с тем же clientMessageId для отправки
503 outcome_unknown да, только с тем же clientMessageId; не отправлять то же в другой канал, пока нет итога
400, 401, 402, 404, 409, 501 нет — сначала исправить причину

Подробно о повторах — в статье Надёжная отправка без дублей.

Обработка в коде

Одна функция-обёртка: повторяет то, что можно повторить, и отдаёт причину остального.

Python

import os
import time
import uuid
import requests

BASE = f"{os.environ['GRATIO_URL']}/waInstance{os.environ['GRATIO_ID']}"
TOKEN = os.environ["GRATIO_TOKEN"]
RETRY = {429, 469, 500, 502, 503, 504}


class GratioError(Exception):
    def __init__(self, status: int, code: str, message: str):
        super().__init__(f"{status} {code}: {message}")
        self.status, self.code = status, code


def call(method: str, payload: dict, attempts: int = 5) -> dict:
    for attempt in range(attempts):
        try:
            r = requests.post(f"{BASE}/{method}/{TOKEN}", json=payload, timeout=90)
        except requests.RequestException:
            time.sleep(2 ** attempt)               # сеть: повтор с паузой
            continue
        if r.status_code == 200:
            return r.json()
        body = r.json() if r.content else {}
        if r.status_code in RETRY and attempt < attempts - 1:
            time.sleep(int(r.headers.get("Retry-After", 2 ** attempt)))
            continue
        raise GratioError(r.status_code, body.get("code", ""), body.get("message", ""))
    raise GratioError(0, "network", "нет связи с API")


# у отправки — ключ от дублей, тогда повтор безопасен
call("sendMessage", {"chatId": "79991234567@c.us", "message": "Здравствуйте!",
                     "clientMessageId": str(uuid.uuid4())})

Node.js

const { GRATIO_URL, GRATIO_ID, GRATIO_TOKEN } = process.env;
const base = `${GRATIO_URL}/waInstance${GRATIO_ID}`;
const RETRY = new Set([429, 469, 500, 502, 503, 504]);
const sleep = (ms) => new Promise((ok) => setTimeout(ok, ms));

export async function call(method, payload, attempts = 5) {
  for (let attempt = 0; attempt < attempts; attempt++) {
    let r;
    try {
      r = await fetch(`${base}/${method}/${GRATIO_TOKEN}`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
        signal: AbortSignal.timeout(90_000),
      });
    } catch {
      await sleep(1000 * 2 ** attempt);          // сеть: повтор с паузой
      continue;
    }
    if (r.ok) return r.json();
    const body = await r.json().catch(() => ({}));
    if (RETRY.has(r.status) && attempt < attempts - 1) {
      await sleep(1000 * Number(r.headers.get("retry-after") ?? 2 ** attempt));
      continue;
    }
    throw Object.assign(new Error(`${r.status} ${body.code}: ${body.message}`), body);
  }
  throw new Error("нет связи с API");
}

await call("sendMessage", {
  chatId: "79991234567@c.us",
  message: "Здравствуйте!",
  clientMessageId: crypto.randomUUID(),
});

Что дальше

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