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

Коды ошибок IZI API

Опубликовано: · IZI Team

Ошибки в GraphQL API возвращаются в поле errors тела ответа, а не через HTTP-статус. HTTP 200 при ошибке — норма. Это надо знать, чтобы не написать обработчик только на HTTP-уровне.

{
"data": null,
"errors": [
{
"message": "Token is expired",
"extensions": {
"code": "TOKEN_EXPIRED",
"timestamp": "2026-05-30T14:32:00Z"
},
"locations": [{ "line": 2, "column": 3 }],
"path": ["me"]
}
]
}

Поля в extensions:

  • code — машиночитаемый код ошибки (используйте его в switch/case)
  • timestamp — время ошибки на сервере
  • field — поле, вызвавшее ошибку (если применимо)
  • details — дополнительный контекст (не всегда присутствует)
КодHTTPОписаниеДействие
UNAUTHENTICATED401Токен отсутствует или не переданДобавьте заголовок Authorization: Bearer <token>
TOKEN_EXPIRED401accessToken истёкОбновите через refreshToken mutation
REFRESH_TOKEN_EXPIRED401refreshToken истёкПовторный логин через loginWithEmailPassword
TOKEN_INVALID401Токен повреждён или поддельныйПроверьте что не обрезали/изменили токен
FORBIDDEN403Нет прав на операциюПроверьте роль пользователя
CLUB_ACCESS_DENIED403Нет доступа к этому клубуПроверьте привязку пользователя к клубу
КодОписаниеДействие
NOT_FOUNDОбъект не существует или не в вашей организацииПроверьте ID и принадлежность организации
ALREADY_EXISTSДубликат при созданииПроверьте уникальные поля (email, phone)
VALIDATION_ERRORДанные не прошли валидациюПроверьте поле details в extensions
INVALID_INPUTНеверный формат входных данныхСверьтесь со схемой GraphQL
КодОписаниеДействие
INSUFFICIENT_BALANCEНедостаточно средств на балансеПроверьте баланс перед операцией
SESSION_ALREADY_ACTIVEНа устройстве уже есть активная сессияЗавершите текущую сессию через endSession
DEVICE_OFFLINEУстройство не в сетиПроверьте статус устройства через deviceStatus
TARIFF_NOT_AVAILABLEТариф недоступен (расписание, зона)Проверьте условия тарифа
CLUB_CLOSEDКлуб закрыт (нет открытой смены)Откройте смену через CRM
CLIENT_BLACKLISTEDКлиент в чёрном спискеОбратитесь к администратору клуба
PAYMENT_FAILEDОшибка платёжного шлюзаПроверьте поле details для кода от эквайера
WEBHOOK_URL_UNREACHABLEURL webhook недоступен при проверкеУбедитесь что endpoint отвечает на GET
КодHTTPОписаниеДействие
RATE_LIMIT_EXCEEDED429Превышен лимит запросовПодождите Retry-After секунд
INTERNAL_SERVER_ERROR500Внутренняя ошибкаПовторите запрос. Если повторяется — в support IZI
SERVICE_UNAVAILABLE503Сервис временно недоступенExponential backoff
async function handleIZIRequest(query, variables) {
const response = await client.request(query, variables);
if (response.errors) {
for (const error of response.errors) {
const code = error.extensions?.code;
switch (code) {
case 'TOKEN_EXPIRED':
await refreshTokens();
return handleIZIRequest(query, variables); // retry
case 'RATE_LIMIT_EXCEEDED':
const retryAfter = error.extensions?.retryAfter || 5;
await sleep(retryAfter * 1000);
return handleIZIRequest(query, variables);
case 'NOT_FOUND':
throw new NotFoundError(error.message);
case 'FORBIDDEN':
throw new PermissionError(error.message);
default:
throw new IZIError(code, error.message, error.extensions);
}
}
}
return response.data;
}

При VALIDATION_ERROR в extensions.details приходит список полей:

{
"code": "VALIDATION_ERROR",
"details": [
{
"field": "input.amount",
"message": "Must be positive number",
"constraint": "min",
"value": -100
}
]
}

Частые вопросы

Почему IZI API возвращает HTTP 200 даже при ошибке?

Это стандартное поведение GraphQL. HTTP-статус 200 означает что запрос был принят и обработан. Бизнес-ошибки возвращаются в поле errors внутри тела ответа. Обрабатывайте оба случая.

Чем отличается FORBIDDEN от UNAUTHORIZED?

UNAUTHORIZED — токен отсутствует, истёк или недействителен. FORBIDDEN — токен валидный, но у этой роли нет прав на операцию.

Что делать при NOT_FOUND?

Проверьте что ID существует и принадлежит вашей организации. IZI возвращает NOT_FOUND и для несуществующих объектов, и для объектов другой организации — чтобы не раскрывать информацию.