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

Основы GraphQL в IZI

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

GraphQL — язык запросов, где вы сами описываете что хотите получить. В отличие от REST, нет множества endpoint’ов: один адрес, один POST, и вы сами выбираете нужные поля.

Если вы раньше работали с REST, главное переключение: забудьте про URL как ресурс. Здесь URL всегда один — https://api.izi.is/graphql, а что делать — описываете в теле запроса.

query GetClub($clubId: ID!) {
club(id: $clubId) {
id
name
timezone
devices {
id
name
status
}
}
}

Разберём по частям:

  • query — тип операции (читать данные)
  • GetClub — имя операции (для логов и отладки, не обязательно но рекомендуется)
  • $clubId: ID! — переменная типа ID, обязательная (!)
  • club(id: $clubId) — вызов поля с аргументом
  • Вложенные поля — выбираем только то, что нужно
query ActiveSessions($clubId: ID!) {
activeSessions(clubId: $clubId) {
id
deviceName
clientName
startedAt
balance
}
}

Переменные передаются отдельным объектом:

{
"clubId": "club_abc123"
}
mutation TopUpClientBalance($input: TopUpInput!) {
topUpBalance(input: $input) {
success
newBalance
transactionId
}
}
{
"input": {
"clientId": "client_xyz",
"amount": 500,
"clubId": "club_abc123"
}
}

Мутации всегда возвращают результат операции. Проверяйте поле success — не полагайтесь только на HTTP 200.

subscription SessionUpdates($clubId: ID!) {
sessionUpdated(clubId: $clubId) {
id
status
deviceId
updatedAt
}
}

Подписки работают через WebSocket. Endpoint для подписок: wss://api.izi.is/graphql.

Никогда не вставляйте данные прямо в строку запроса — это и уязвимость, и неудобство:

# ❌ Плохо — интерполяция в строке
query { club(id: "club_abc123") { name } }
# ✅ Хорошо — переменные
query GetClub($id: ID!) {
club(id: $id) { name }
}
# Переменные: { "id": "club_abc123" }

Если одни и те же поля нужны в нескольких запросах — выносите в фрагменты:

fragment DeviceFields on Device {
id
name
status
zone {
id
name
}
}
query AllDevices($clubId: ID!) {
devices(clubId: $clubId) {
...DeviceFields
}
}

Ответ IZI API всегда содержит data и опционально errors:

{
"data": {
"topUpBalance": null
},
"errors": [
{
"message": "Insufficient permissions",
"extensions": {
"code": "FORBIDDEN",
"field": "topUpBalance"
}
}
]
}

HTTP-статус при этом может быть 200. Обрабатывайте поле errors явно — не полагайтесь на HTTP-коды для бизнес-ошибок. Полный список кодов — Коды ошибок API.

Посмотреть всю схему:

{
__schema {
types {
name
kind
description
}
}
}

Посмотреть поля конкретного типа:

{
__type(name: "Club") {
fields {
name
type { name kind }
description
isDeprecated
deprecationReason
}
}
}

Несколько операций за один HTTP-запрос:

[
{ "query": "query { me { id } }" },
{ "query": "query { clubs { id name } }" }
]

Ответ — массив в том же порядке. Лимит: 10 операций в батче.

КлиентДля чего
InsomniaРазработка и отладка запросов
Apollo ClientFrontend (React/Vue)
graphql-requestNode.js скрипты и backend
gql + httpxPython

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

Чем query отличается от mutation в IZI API?

query читает данные без изменения состояния. mutation изменяет данные: создаёт сессию, пополняет баланс, обновляет тариф. Правило простое: если операция что-то меняет — это mutation.

Можно ли передавать несколько запросов в одном POST?

Да, это называется batching. Передайте массив операций в теле запроса. IZI API поддерживает batch до 10 операций за раз.

Как узнать все доступные поля и типы?

Используйте introspection: отправьте запрос __schema или __type. Большинство GraphQL-клиентов (Insomnia, Apollo Studio) делают это автоматически.

Что значит N+1 проблема и как IZI её решает?

N+1 — когда для списка из N объектов делается N дополнительных запросов. IZI API использует DataLoader: связанные объекты загружаются батчами автоматически.