Ошибки, диагностика и надёжность
Как читать ошибки API кассового сервера, что делать в каждом случае и как построить интеграцию, которая не задваивает налоговые документы.
1. Где какая ошибка появляется#
Ошибки приходят в двух местах, и это разные классы проблем:
| Где | Класс | Пример |
|---|---|---|
| В ответе на регистрацию (HTTP 4xx) | Запрос не принят: авторизация, схема чека, несовпадение ИНН, дубль | 10, 11, 12, 32, 33 |
В результате документа (report, документ уже принят) |
Не удалось пробить: касса офлайн, отказ кассы | 2001, 2002, type: "timeout" с кодом 1, ошибки драйвера |
Первый класс исправляется в коде интеграции. Второй — на стороне кассы и оборудования.
Коды 2001, 2002 и 2003 сервис выдаёт: 2001 — за 300 с чеку так и не досталась касса (все офлайн либо заняты), 2002 — касса не умеет такой чек, 2003 — ИНН чека не совпадает с ИНН группы (отвечаем сразу на регистрации, HTTP 400). Разбор каждого — ниже.
2. Ошибки запроса#
10 · 11 · 12 — авторизация#
| Код | Причина | Решение |
|---|---|---|
| 10 | Токен не передан | Заголовок Token: <токен> или ?token= |
| 11 | Токен истёк (живёт 24 часа) или неизвестен | Получить новый через getToken |
| 12 | Неверный логин или пароль | Проверить реквизиты группы |
| 20 | Токен выдан для другой группы | Сверить group_code в пути |
| 21 | Группа не работает по этой версии протокола | Проверить v5 / v4 в пути |
Практика: кэшируйте токен на 23 часа и обновляйте по ошибке 11, а не по расписанию.
32 — валидация чека#
Самая частая ошибка на старте интеграции. Текст всегда называет конкретное поле, например:
{ "error": { "code": 32, "type": "system",
"text": "items[0].measure обязателен (v5, тег 2108)" } }
Типовые причины:
| Текст ошибки | Что не так |
|---|---|
receipt.client: обязателен минимум один из email|phone |
Электронный чек некуда отправить |
receipt.company.inn: ожидается 10 или 12 цифр |
ИНН с пробелами, дефисами или не тот |
items[N].payment_object обязателен (v5) |
Не передан признак предмета расчёта |
items[N].measure обязателен (v5, тег 2108) |
Единица измерения строкой вместо кода |
items[N].measurement_unit не поддерживается в v5 |
Смешаны v4 и v5 в одном чеке |
receipt.total (…) не равен сумме позиций (…) |
Скидка вычтена из total, но не из позиций |
сумма оплат (…) не равна receipt.total (…) |
Округление в оплате |
items[N].supplier_info с валидным inn обязателен при agent_info |
Агентская позиция без поставщика |
receipt.company.inn (…) не совпадает с ИНН группы (…) |
ИНН чека не тот, на который зарегистрирован ФН касс группы |
Сверьте состав чека со справочником реквизитов — там перечислено, что обязательно в v5, а что в v4.
Последняя строка — про ИНН — отрабатывается до постановки в очередь: чек с чужим ИНН отклоняется сразу (HTTP 400, код 32), документ не создаётся и external_id не расходуется. Сверьте ИНН с карточкой регистрации ККТ и с реквизитами, указанными при создании кассового сервера.
33 — дубль external_id#
Это не ошибка интеграции, а штатный ответ на повтор. В теле ответа приходит uuid первого документа:
{ "uuid": "47b30214-…", "status": "wait",
"error": { "code": 33, "text": "документ с таким external_id уже принят в этой группе" } }
Правильная реакция: взять uuid и запросить по нему report. Ошибкой это становится только если вы случайно переиспользовали external_id для другого расчёта.
30 · 34 — работа с report#
- 30 — неизвестный
uuid: опечатка, чужая группа или документ старше 60 дней (архив). - 34 — документ ещё не обработан. Приходит с HTTP 200 и
status: wait; просто продолжайте ждать.
429 — превышен лимит#
Регистрация ограничена 10 запросами в секунду на группу, поллинг — 1 запрос в секунду на каждую кассу группы. Повторите с задержкой; для поллинга разумный интервал — 2–3 секунды, а лучше подписаться на callback_url.
3. Ошибки в report: документ принят, но не пробит#
Код 2001 (type: "timeout") — 300 секунд ожидания кассы#
Документ пролежал в очереди 5 минут и не дождался онлайн-кассы группы: кассовый ПК выключен, нет интернета, мост не запущен — либо все кассы группы заняты другими документами дольше отведённого времени. Текст ошибки: «очередь: за 300 с в группе не нашлось свободной кассы (все кассы офлайн либо заняты)».
Отдельно от него стоит код 1 с тем же type: "timeout": касса чек ВЗЯЛА, но за 300 с не отчиталась о результате (зависла, оборвалась связь в момент печати). Здесь, в отличие от 2001, документ мог уйти в ФН — прежде чем повторять расчёт, сверьте последний чек на самой кассе.
Что делать:
- Проверить, что кассовый ПК включён и мост запущен (страница статуса моста на самом ПК); связь каждой кассы видна и в админке — раздел «API кассы»;
- Проверить связь ПК с интернетом;
- Если ПК и мост в порядке, а таймауты повторяются на пиках — добавить в группу вторую кассу, в том числе резервную: очередь обслуживает документы по времени поступления;
- Повторить расчёт новым
external_id— старый документ уже финализирован какfail.
Ошибки драйвера кассы#
Всё, что касса ответила сама, приходит её текстом: «нет бумаги», «касса заблокирована», «открыт незавершённый чек», «ФН переполнен», «смена превысила 24 часа — снимите Z-отчёт» (см. Смена больше 24 часов). Разбор частых кодов — Ошибки АТОЛ и Ошибки ШТРИХ-М.
Сюда же попадает и несовместимость чека с моделью кассы — такой отказ приходит с кодом 2002 и текстом драйвера:
- ККТ не умеет электронный чек без печати — для интернет-расчётов это обязательное свойство (сегодня уверенно поддерживают кассы АТОЛ);
- в чеке есть маркировка, а касса без поддержки ФФД 1.2;
- расширенные реквизиты покупателя или отраслевые реквизиты, которых модель не знает.
Что делать: проверить модель кассы и версию ФФД; при необходимости завести в группу подходящий аппарат. Отбор кассы «по способностям» очередь не делает — документ уходит на любую онлайн-кассу группы, поэтому в одной группе держите однотипные по возможностям аппараты.
4. Защита от двойного чека#
Двойной налоговый документ на одну оплату — худшая из возможных ошибок фискальной интеграции: его придётся сторнировать чеком коррекции и объясняться с ФНС. В сервисе против этого работают три рубежа:
external_idна приёме. Повтор в пределах группы возвращает прежнийuuid(ошибка 33) и никогда не создаёт второй документ.- Ключ операции до самой кассы. Мост получает ключ, построенный из группы и
external_id, и ведёт журнал операций на диске. Повтор возвращает первый результат — даже если кассовый ПК успел перезагрузиться. - Честный отказ при неизвестном исходе. Если связь оборвалась ровно в момент закрытия чека (документ мог уйти в ФН, а мог и нет), повтор этой операции отклоняется с требованием сверить последний документ на кассе. Вслепую второй чек не пробивается.
Что требуется от вашей стороны:
- один расчёт — один
external_id, стабильный при ретраях (напримерorder-10421, а не случайный UUID на каждую попытку); - никогда не менять
external_id«чтобы прошло»: если документ не пробился, сначала выясните почему; - обработчик callback — идемпотентный: одно и то же уведомление может прийти повторно.
5. Что делать, если касса офлайн#
Кассовый ПК выключен или без интернета — чек не пробьётся: касса физически ваша, и облако не может её заменить. Поведение сервиса:
- документ ждёт в очереди до 300 секунд;
- если касса появилась в это время — чек пробивается штатно;
- если нет — документ переходит в
failс типомtimeout.
Рекомендации для магазинов с круглосуточным приёмом заказов:
- Держать кассовый ПК включённым (энергосбережение и «сон» — выключить);
- Поставить вторую кассу в группу как резервную;
- В своей системе иметь очередь неотправленных чеков и повторять их новым
external_id, когда касса вернулась онлайн, — с учётом того, что по закону чек формируется не позднее следующего рабочего дня; - Настроить мониторинг:
failсtimeout— это инцидент, о котором должен узнать человек.
6. Чек-лист перед запуском в бой#
- ККТ зарегистрирована с признаком «расчёты в Интернете», в теге 1187 — адрес сайта;
- ИНН в
receipt.company.innсовпадает с ИНН регистрации ФН; - СНО в чеке соответствует вашей реальной системе налогообложения;
-
external_idдетерминирован и переживает ретраи; - обработан ответ 33 (взять
uuidиз ответа, не считать это сбоем); - реализован и поллинг, и
callback_url— второй не заменяет первый; - признание оплаты фискализированной — только по
status: done; - ФД, ФПД, ФН и РН ККТ сохраняются в заказе;
-
failиtimeoutпопадают в мониторинг, а не только в лог; - проверено поведение при выключенном кассовом ПК;
- для маркированных товаров проверка кода выполняется до отправки чека;
- проверены ставки НДС на реальной прошивке кассы (особенно 22 % и расчётные).
7. Куда смотреть при разборе инцидента#
| Вопрос | Где ответ |
|---|---|
| Что именно мы отправили | Ваш лог запроса + external_id |
| Что ответил сервис | report по uuid (хранится не менее 32 суток) |
| Дошло ли до кассы | device_code в report — код кассы, на которую ушёл документ |
| Что сказала касса | Поле error в report; журнал чеков и последняя ошибка — в разделе «API кассы» |
| Есть ли чек в ФН | Номер ФД из payload + личный кабинет ОФД |
| Был ли повтор | Ошибка 33 в ваших логах и совпадающий uuid |
Поле
error— всегда объект{error_id, code, text, type}, в том числе при отказе драйвера: текст кассы приходит от моста строкой, а сервис заворачивает его в объект и проставляет код (2002— касса не умеет такой чек,1— прочий отказ) иtype: "driver".error_idу одного и того же отказа не меняется между поллингами — его можно указывать в обращении в поддержку.
Если чек пробит, а ваша система об этом не узнала (потеряли callback и не поллили), документ всё равно существует: найдите его по external_id через report и досохраните реквизиты — повторно пробивать не нужно.
Дальше: справочник API · реквизиты чека · сценарии магазина.