Прочитайте ответ ошибки
Сначала проверьте HTTP-статус. statusCode повторяет его. error содержит ключ перевода общей HTTP-категории, например errors:http.conflict; он не определяет конкретную бизнес-причину.
Ответ Hallify содержит стабильный code: доменный код, если он задан, либо стандартный HTTP_*, например HTTP_UNAUTHORIZED. Используйте статус и документированный код для программной логики. Структурированные доменные данные могут находиться в details. Поддерживаемые статусы и детали описаны в конкретной операции.
message и translationKey содержат один и тот же стабильный ключ перевода, а не готовое английское или русское предложение. Необязательное поле translationValues содержит скалярные данные для параметров шаблона. Переводите ключ в своём приложении: бэкенд не выбирает язык интерфейса, а добавление нового языка не меняет API-ответ.
validationErrors, если поле присутствует, указывает ошибочное field, код валидатора code и ключи в message и translationKey. Вложенные поля задаются путями через точку, включая индексы массивов. Сопоставляйте поле с ограничениями документированной схемы. Введённые значения и произвольные тексты валидаторов не возвращаются.
Каталог ключей объясняет опубликованные ключи через те же локальные ресурсы переводов, что использует клиент Hallify. В другом клиенте можно использовать собственные переводы. Для неизвестных ключей и отсутствующих переводов показывайте локализованное запасное сообщение, а не сам ключ. Обрабатывайте translationValues как обычные данные, а не HTML или настройки библиотеки переводов.
Сохраняйте статус/код для диагностики, не записывая секреты и приватное содержимое запросов. Сам по себе HTTP 409 не означает, что повтор безопасен. Непредвиденные или незарегистрированные ошибки получают стандартный ключ своего HTTP-статуса без внутренних диагностических текстов.
Этот формат применяется к ответам общего обработчика HTTP-исключений Hallify. Успешные подтверждения, протоколы обратных вызовов провайдеров, уже начатые потоки и ошибки инфраструктуры или прокси могут иметь другой формат. Следуйте контракту операции и проверяйте Content-Type перед разбором JSON. Пользовательские имена, комментарии и другой бизнес-контент остаются данными.
{
"statusCode": 409,
"error": "errors:http.conflict",
"code": "IDEMPOTENCY_REQUEST_IN_PROGRESS",
"message": "errors:idempotency.inProgress",
"translationKey": "errors:idempotency.inProgress"
}Безопасно повторите ту же команду
Для методов с Idempotency-Key создавайте один ключ на логическую команду и сохраняйте его при сетевых повторах с тем же содержимым. Повторное использование с другим содержимым вызывает конфликт. Идемпотентность определяется конкретным методом и не распространяется автоматически на любой POST.
При конфликте ревизии прочитайте актуальную запись и проверьте допустимость действия. Не повторяйте вслепую истёкший расчёт, использованный начальный доступ или неверный код подтверждения.
Различайте конфликты идемпотентности
Эти коды относятся только к методам, которые документируют общую схему конфликтов идемпотентности. Другие интеграции могут использовать свои протоколы конфликтов и повторов.
IDEMPOTENCY_REQUEST_IN_PROGRESS: предыдущий запрос с этим ключом ещё обрабатывается. Подождите и повторите запрос с тем же ключом и идентичным телом. Новый ключ может привести к повторному выполнению действия.
IDEMPOTENCY_KEY_PAYLOAD_MISMATCH: ключ уже связан с другим телом запроса. Для повтора восстановите исходное тело. Для другой бизнес-команды сначала проверьте результат исходной и назначьте новый ключ.
IDEMPOTENCY_REQUEST_NOT_READY: сохранённый результат пока недоступен. Повторите запрос с исходными ключом и телом, ограничив число попыток и увеличивая паузу. Если ошибка сохраняется, обратитесь в поддержку интеграций.
IDEMPOTENCY_SCOPE_INCOMPLETE: сервер не смог определить нужную организацию или заведение. Проверьте адрес метода и требуемый контекст; если они верны, обратитесь в поддержку интеграций. Не запускайте неизменённый запрос снова и снова.
Восстанавливайте исходную команду брони или соглашения
Разделяйте квитанции create-intent/resend/verify и currentState/current. Недоступное текущее обогащение или неизвестная доставка не означают провал сохранённой команды. read-intent читает обезличенную проверку в исходном контексте; использованное намерение не перевыдаёт manage-доступ. Потерянный ответ восстанавливайте тем же ключом и точным телом без заменяющей брони или проверки.
RESERVATION_GUARANTEE_TERMS_CHANGED требует нового просмотра точных нативных условий перед новым явным действием. RESERVATION_GUARANTEE_ACCEPTANCE_REQUIRED означает отсутствие или непригодность нужного исходного доказательства/digest. RESERVATION_GUARANTEE_AGREEMENT_CHANGED или RESERVATION_GUARANTEE_REAGREEMENT_REQUIRED требуют чтения фактической текущей брони/предложения и просмотра действующего соглашения; не подменяйте сохранённый hash, не пересчитывайте принятое обязательство и не обходите срок.
Исходная квитанция соглашения ACCEPTED может сосуществовать с незавершённым возвратом/освобождением старых средств, неизвестным платежом или недоступной вместимостью. Она не доказывает ACTIVATED и не восстанавливает терминальную бронь. manageAccessState: REPROOF_REQUIRED и currentState: UNAVAILABLE не отменяют согласие и не разрешают вторую оплату. Сохраняйте исходную команду, используйте текущее разрешённое управление и восстановление исходного платежа; скрытая недоступность не разрешает перебор ресурсов или staff/account fallback.
Восстанавливайте исходную оплату без замены команды
Платёжный допуск и checkout используют собственные стабильные коды. GUEST_PAYMENT_INPUT_INVALID и INVALID_GUEST_PAYMENT_INPUT означают неверный ввод. GUEST_PAYMENT_SOURCE_CHANGED, GUEST_PAYMENT_CONSENT_CHANGED и GUEST_PAYMENT_QUOTE_STALE требуют проверки текущих полномочий и точного просмотренного предложения. Скрытая недоступность не разрешает искать другой ресурс, подставлять аккаунт или переписывать Origin.
После потери ответа create сохраняйте исходный ключ команды и точное согласие. POST commands/recover читает первое неизменяемое PREPARED acknowledgement; GET progress читает текущее состояние операции, средств и нативного применения. Эти методы не выделяют заменяющую команду. PREPARED acknowledgement, redirect провайдера и query-параметр outcome не означают успешную оплату.
POST recovery checkout имеет другой смысл: явное действие пользователя может получить исходный финансовый permit или повторить точный исходный Stripe CREATE в разрешённых условиях. Не вызывайте его автоматически после reload/return. UNKNOWN, повторяемый decline и сетевая ошибка требуют сохранения сценария и незавершённых holds; только доказанный серверный terminal допускает явную новую оплату.
Повтор, неизменённый offer и handoff не обновляют исходный финансовый срок. Offer действует до пяти минут; исходный финансовый доступ — до пятнадцати минут; раскрытие собственного результата — до двадцати четырёх часов и в пределах текущих нативных полномочий/представления. Срок результата не возвращает право расходования и не даёт доступ к другому checkout.
Для widget transition сохраните исходные permit и receiver tuple до отправки. Потерянные prepare/claim acknowledgements повторяются с точным исходным предложением и замороженным сроком, в том числе после consumption. Отсутствующий saved receiver нельзя исправить другой tuple. Отказ context/authority не разрешает cookie fallback, поддельный Origin или автоматическую заменяющую оплату.
Учитывайте лимиты и сроки
При ответе 429 соблюдайте Retry-After в целых секундах. Лимиты настраиваются по доменам и каналам; единой опубликованной квоты для всех интеграций нет. Проверяйте размеры запросов, массивов и ограничения полей в справочнике.
401 может означать отсутствующий, неверный, истёкший или отозванный доступ либо устаревшую подпись. Скрытый 404 может быть связан с областью доступа. При недоступной настройке провайдера обратитесь к администратору ресторана; не меняйте production-данные только для проверки связи.