Skip to content

IZI API Error Codes

Published: · IZI Team

Errors in the GraphQL API are returned in the errors field of the response body, not via HTTP status. HTTP 200 on an error is normal. Knowing this upfront prevents writing a handler that only checks HTTP codes.

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

Fields in extensions:

  • code — machine-readable error code (use in switch/case)
  • timestamp — server-side error time
  • field — field that caused the error (when applicable)
  • details — additional context (not always present)
CodeHTTPDescriptionAction
UNAUTHENTICATED401Token missing or not providedAdd Authorization: Bearer <token> header
TOKEN_EXPIRED401accessToken expiredRefresh via refreshToken mutation
REFRESH_TOKEN_EXPIRED401refreshToken expiredRe-login via loginWithEmailPassword
TOKEN_INVALID401Token corrupted or forgedCheck that the token hasn’t been truncated or modified
FORBIDDEN403No permission for the operationCheck user role
CLUB_ACCESS_DENIED403No access to this clubCheck user’s club assignment
CodeDescriptionAction
NOT_FOUNDObject doesn’t exist or belongs to another organizationCheck ID and organization ownership
ALREADY_EXISTSDuplicate on creationCheck unique fields (email, phone)
VALIDATION_ERRORData failed validationCheck details field in extensions
INVALID_INPUTWrong input formatCheck against the GraphQL schema
CodeDescriptionAction
INSUFFICIENT_BALANCENot enough fundsCheck balance before the operation
SESSION_ALREADY_ACTIVEDevice already has an active sessionEnd the current session via endSession
DEVICE_OFFLINEDevice is not onlineCheck device status via deviceStatus
TARIFF_NOT_AVAILABLETariff unavailable (schedule, zone)Check tariff conditions
CLUB_CLOSEDClub is closed (no open shift)Open a shift in the CRM
CLIENT_BLACKLISTEDClient is blacklistedContact the club admin
PAYMENT_FAILEDPayment gateway errorCheck details for the acquirer error code
WEBHOOK_URL_UNREACHABLEWebhook URL unreachable during checkMake sure endpoint responds to GET
CodeHTTPDescriptionAction
RATE_LIMIT_EXCEEDED429Request limit exceededWait Retry-After seconds
INTERNAL_SERVER_ERROR500Internal server errorRetry. If it persists — contact IZI support
SERVICE_UNAVAILABLE503Service temporarily unavailableExponential 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);
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;
}

For VALIDATION_ERROR, extensions.details contains a field list:

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

Frequently asked questions

Why does IZI API return HTTP 200 even on errors?

This is standard GraphQL behavior. HTTP 200 means the request was received and processed. Business errors are returned in the errors field inside the response body. Handle both cases.

What is the difference between FORBIDDEN and UNAUTHORIZED?

UNAUTHORIZED means the token is missing, expired, or invalid. FORBIDDEN means the token is valid but the role doesn't have permission for the operation.

What to do on NOT_FOUND?

Check that the ID exists and belongs to your organization. IZI returns NOT_FOUND for both non-existent objects and objects from another organization — to avoid leaking information.