API v1 Справочник Личный кабинет

API для разработчиков

Выдавайте гостям доступ к Wi-Fi прямо из своей системы: оплата в коворкинге, бронь в отеле, регистрация на конференции. Забирайте статистику в свой дашборд и гасите купоны на кассе.

REST + JSONОбычный HTTP, ключ в заголовке. Никаких SDK не нужно.
Тариф «Про»Ключи выпускает владелец аккаунта в разделе «API».
Без персональных данныхНаружу телефоны и ФИО отдаются только под маской.

Быстрый старт

Три шага до первого выданного кода Wi-Fi:

  1. В личном кабинете откройте API (раздел виден владельцу аккаунта) и выпустите ключ с правом «Запись». Секрет показывается один раз — сохраните его.
  2. Узнайте place_id своего заведения — запросом GET /places.
  3. Выдайте гостю код — POST /vouchers. В ответе придёт code, его называете гостю.
# 1. какие у меня заведения
curl https://api.iwifi.ru/v1/places \
  -H "Authorization: Bearer iw_live_ВАШ_КЛЮЧ"

# 2. выдать код на 3 часа
curl -X POST https://api.iwifi.ru/v1/vouchers \
  -H "Authorization: Bearer iw_live_ВАШ_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{
    "place_id": 1,
    "phone": "79991234567",
    "valid_to": "2026-07-20T18:00:00",
    "limits": { "minutes_total": 180, "speed_mbit": 50 }
  }'

Ответ (сокращённо) — единственный раз, когда виден код:

{
  "data": {
    "id": 42,
    "type": "code",
    "code": "k7rm2xq4",          <-- показываете гостю
    "valid_to": "2026-07-20T18:00:00+00:00",
    "guest": { "phone": "*********67" },
    "limits": { "minutes_total": 180, "speed_mbit": 50 }
  }
}

Гость подключается к Wi-Fi, вводит k7rm2xq4 на странице входа — и в сети. Доступ открывается мгновенно.

Ключ и авторизация

Базовый адрес — https://api.iwifi.ru/v1. Все запросы — с заголовком Authorization: Bearer <ключ>. Ключ имеет вид iw_live_….

Старый адрес https://iwifi.ru/api/v1/… продолжает работать и ломаться не будет — но в новых интеграциях используйте api.iwifi.ru.

curl https://api.iwifi.ru/v1/points -H "Authorization: Bearer iw_live_ВАШ_КЛЮЧ"

У ключа два измерения доступа, настраиваются при выпуске:

ПравоЧто разрешает
readВсе GET-запросы: заведения, точки, сессии, статистика, купоны.
writeИзменения: выдача кодов, заселение, гашение купонов.

Ключ только с «Запись» — нормальный выбор, если система делает одну операцию (касса, которая лишь гасит купоны: базу гостей ей видеть незачем). Но он не сможет вызвать и GET /placesplace_id тогда возьмите в кабинете и пропишите в своей системе. Для обычной интеграции берите оба.

И скоуп заведений: ключ можно ограничить одним заведением — тогда он не увидит и не тронет остальные.

Ключ — это пароль к данным аккаунта. Мы храним только его отпечаток и не можем показать повторно. Потеряли — выпустите новый и отзовите старый. Не кладите ключ в мобильное приложение или JS на сайте: оттуда его достанут. Ключ должен жить на вашем сервере.

Ограничение по IP — включите его

У каждого ключа можно указать список разрешённых адресов (в кабинете, поле «Разрешённые IP»): одиночные адреса и подсети, например 195.24.67.10, 10.0.0.0/24. Запрос с любого другого адреса получит 403 ip_not_allowed — даже с правильным ключом.

Это самая эффективная защита ключа. Ваша система ходит к API с одного-двух серверных адресов — разрешите только их. Тогда утёкший ключ бесполезен: без вашего сервера он не работает. В кабинете рядом с ключом показаны адреса, с которых он уже обращался, — можно добавить их в список одним кликом.

Журнал и уведомления

Все обращения (включая отказы) пишутся в журнал — он виден в кабинете, в разделе «API»: время, ключ, метод, путь, код ответа, IP. Храним 90 дней. По журналу видно и подбор ключа, и запросы с чужого адреса.

Если ключ впервые использован с нового IP-адреса, владелец аккаунта получает письмо — на случай, если ключ попал не в те руки. Уведомление приходит один раз на каждый новый адрес; на первый (когда вы настраиваете интеграцию) — не приходит. Отключается в разделе «Отчёты».

Формат и ошибки

Успешный ответ всегда в поле data, списки дополнены meta. Ошибка — всегда в поле error:

{
  "error": {
    "code": "identification_required",
    "message": "Гость должен быть идентифицирован: передайте phone (от 10 цифр) либо fio + document.",
    "details": { "accepted": ["phone", "fio+document"] }
  }
}

Ориентируйтесь на code — он стабилен, на него можно писать логику. message может меняться.

HTTPcodeЧто делать
401unauthorized, invalid_keyНет заголовка или ключ отозван.
402tariff_requiredAPI доступен на тарифе «Про».
403insufficient_scope, place_forbidden, ip_not_allowedКлючу не хватает права, заведение вне доступа или запрос с неразрешённого IP.
404not_found, code_not_foundОбъект не найден (или не ваш).
409login_taken, already_redeemed, coupon_expiredКонфликт состояния — повтор не поможет.
422validation_failed, identification_requiredПоправьте тело запроса.
429rate_limitedПодождите, см. заголовок Retry-After.
500internal_errorНаша ошибка. Повторите позже; если повторяется — напишите в поддержку.

Лимиты и идемпотентность

Частота запросов

120 запросов в минуту на ключ. Текущий остаток — в заголовках ответа:

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 1784138100

При превышении — 429 и Retry-After с числом секунд до сброса.

Пагинация

Списки: ?limit= (по умолчанию 50, максимум 200) и ?offset=. Общее число — в meta.total.

Идемпотентность

Сеть подвела, ответ не дошёл, вы повторили запрос — и гость получил два кода вместо одного. Чтобы этого не было, передавайте заголовок Idempotency-Key с уникальным значением операции (например, номер заказа):

curl -X POST https://api.iwifi.ru/v1/vouchers \
  -H "Authorization: Bearer iw_live_ВАШ_КЛЮЧ" \
  -H "Idempotency-Key: order-12345" \
  -H "Content-Type: application/json" \
  -d '{ "place_id": 1, "phone": "79991234567", "valid_to": "2026-07-20T18:00:00" }'

Повтор с тем же ключом вернёт тот же самый ваучер (в ответе будет заголовок Idempotent-Replay: true), а не создаст второй. Ключи хранятся 3 суток. Тот же ключ с другим телом запроса — ошибка idempotency_key_reused: так мы ловим случайное переиспользование.

Персональные данные

API не отдаёт персональные данные гостей. В любом ответе телефон приходит как *********67, ФИО и документ — как ******, MAC — как **:**:**:**:**:48. Это осознанное решение: ключ не может «утечь вместе с базой». Полные данные видны только в личном кабинете — там показ защищён отдельным кодом на почту владельца и пишется в журнал доступа к ПДн.
А на запись — наоборот, ПДн обязательны. При выдаче доступа нужно передать phone (от 10 цифр) либо fio + document. Так требует ПП РФ 2606/2607: гость публичного Wi-Fi должен быть идентифицирован в момент выдачи доступа. Когда код выдаёт ваша система, идентификацию проводит она — у вас уже есть телефон клиента при оплате или брони. Именно поэтому автоматическая выдача кодов через API законна, а «пачка анонимных кодов на распечатке» — нет.

Заведения

GET/places

Заведения, доступные ключу. Отсюда берётся place_id для остальных запросов.

{
  "data": [
    {
      "id": 1,
      "name": "Кофейня на Тверской",
      "address": "Тверская, 1",
      "timezone_utc_offset": 3,
      "legal_entity": { "name": "ООО «Ромашка»", "inn": "7701234567" },
      "auth_methods": ["phone_call", "sms", "voucher"]
    }
  ],
  "meta": { "count": 1 }
}

auth_methods — включённые способы входа гостя. Если там нет voucher, выданный код работать не будет: включите вход по коду в настройках заведения.

Точки доступа

GET/points

Роутеры заведения и их состояние. Точка online, если сейчас есть гости или была активность за последние 15 минут.

{
  "data": [
    {
      "id": 5, "place_id": 1, "name": "Зал", "nas_id": "m8JMLqqDFp",
      "enabled": true, "status": "online", "guests_online": 3,
      "last_activity_at": "2026-07-15T14:22:10+00:00"
    }
  ]
}
Удобно для мониторинга: заберите статус в Zabbix и получите алерт, если точка «замолчала» в рабочее время. (Такой же алерт умеет присылать сам кабинет — в разделе «Отчёты».)

Коды Wi-Fi (ваучеры)

Главный сценарий API: гость оплатил час в коворкинге, забронировал домик, зарегистрировался на конференцию — ваша система выдаёт ему доступ.

POST/vouchers
ПолеТипОписание
place_id *intЗаведение (из GET /places).
valid_to *date-timeДо какого момента действует.
phonestringТелефон гостя, от 10 цифр. Обязателен, если нет fio+document.
fio, documentstringАльтернатива телефону: ФИО и документ.
typestringcode (по умолчанию) — одна строка, генерируем мы. login_password — свои логин и пароль.
valid_fromdate-timeПо умолчанию — сейчас.
scopestringclient — код действует во всех ваших заведениях.
limitsobjectspeed_mbit, minutes_total, minutes_per_day, traffic_mb_total, traffic_mb_per_day. Не передан — действуют лимиты точки.
email, roomstringНеобязательные.
GET/vouchers

Фильтры: ?place_id=, ?status=active|expired|blocked, плюс пагинация. Код в списке не возвращается.

PATCH/vouchers/{id}

Продлить или перекрыть доступ. Блокировка действует немедленно — гостя отключит от сети:

# продлить
curl -X PATCH https://api.iwifi.ru/v1/vouchers/42 -H "Authorization: Bearer iw_live_КЛЮЧ" \
  -H "Content-Type: application/json" -d '{"valid_to": "2026-07-21T18:00:00"}'

# заблокировать
curl -X PATCH https://api.iwifi.ru/v1/vouchers/42 -H "Authorization: Bearer iw_live_КЛЮЧ" \
  -H "Content-Type: application/json" -d '{"blocked": true}'
DELETE/vouchers/{id}

Удалить ваучер и снять доступ.

Проживающие (отели)

Гость отеля входит в Wi-Fi по фамилии латиницей и номеру комнаты — отдельный код не нужен. Заселяйте гостей из своей АСУ этим методом.

POST/residents
curl -X POST https://api.iwifi.ru/v1/residents \
  -H "Authorization: Bearer iw_live_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: booking-98765" \
  -d '{
    "place_id": 1,
    "room": "501",
    "surname_lat": "PETROV",
    "fio": "Петров Пётр Петрович",
    "phone": "79993334455",
    "check_out": "2026-07-22T12:00:00"
  }'
ПолеОписание
place_id *Заведение (отель).
room *Номер комнаты — его гость вводит при входе.
surname_lat *Фамилия латиницей — второй «пароль» гостя.
check_out *Дата выезда: доступ выключится сам.
check_inПо умолчанию — сейчас.
phone / fio+documentИдентификация гостя (обязательна).

Ещё: GET /residents (фильтры ?room=, ?status=living|upcoming|left), PATCH /residents/{id} (продлить, сменить комнату), DELETE /residents/{id} (досрочно выселить).

Если ваша АСУ — Bnovo или TravelLine, API не нужен: у нас есть готовый приём вебхуков, настраивается в кабинете без кода.

Сессии

GET/sessions

Подключения гостей. Фильтры: ?place_id=, ?point_id=, ?from=, ?to=, ?status=online.

{
  "data": [
    {
      "id": "a1b2c3", "place_id": 1, "nas_id": "m8JMLqqDFp",
      "guest_ref": "*********67",
      "auth_method": "sms", "auto_login": false,
      "mac": "**:**:**:**:**:48", "ip": "10.0.0.15",
      "started_at": "2026-07-15T12:01:00+00:00", "stopped_at": null,
      "online": true, "duration_sec": 1840,
      "traffic_bytes": { "in": 4301647, "out": 1120400, "total": 5422047 },
      "device": "iPhone", "os": "iOS"
    }
  ],
  "meta": { "count": 1, "total": 508, "limit": 50, "offset": 0 }
}

guest_ref — маска телефона, либо логин ваучера/сотрудника, либо resident:<id>.

Статистика

GET/stats

Агрегаты за период (по умолчанию 30 дней): ?from=, ?to=, ?place_id=. Готово для выгрузки в BI.

{
  "data": {
    "period": { "from": "2026-06-15T00:00:00+00:00", "to": "2026-07-15T23:59:59+00:00" },
    "totals": { "sessions": 508, "guests": 16, "traffic_bytes": 2051817545, "avg_session_sec": 4614 },
    "by_place":  [ { "place_id": 1, "name": "Кофейня", "sessions": 508, "guests": 16, "traffic_bytes": 2051817545 } ],
    "by_method": { "sms": 276, "phone_call": 37, "voucher": 17, "vk": 14 },
    "by_day":    [ { "date": "2026-07-15", "sessions": 24, "guests": 9, "traffic_bytes": 91234567 } ]
  }
}

Купоны

POST/coupons/redeem

Гашение промокода на кассе. Принимает и уникальный код из пула, и общий промокод акции — кассиру не нужно знать тип. Регистр и дефисы не важны.

curl -X POST https://api.iwifi.ru/v1/coupons/redeem \
  -H "Authorization: Bearer iw_live_КЛЮЧ" \
  -H "Content-Type: application/json" \
  -d '{"code": "K7RM2XQ4"}'

# ответ
{ "data": { "redeemed": true, "type": "unique",
            "coupon": { "id": 8, "title": "Осенняя акция", "offer": "Кофе в подарок" } } }

Повторное гашение — 409 already_redeemed. Просрочка — 409 coupon_expired. Неизвестный код — 404 code_not_found.

GET/coupons

Список акций со счётчиками показов и погашений.

Готовые сценарии

Коворкинг: оплатил час — получил код

После успешной оплаты вызовите POST /vouchers с телефоном клиента и minutes_total по тарифу. Код покажите на экране и продублируйте в SMS/письме. Номер платежа передайте как Idempotency-Key — повторный колбэк платёжки не выдаст второй код.

База отдыха: бронь — код в письме

При подтверждении брони — POST /vouchers, где valid_from = заезд, valid_to = выезд. Код вставьте в письмо с бронью: гость приезжает и сразу в сети.

Конференция: код в бейдж

На каждого зарегистрированного — POST /vouchers с его ФИО и телефоном. Код печатайте на бейдже. Один участник — один код: это и требование закона, и защита от «расшаривания» кода наружу.

Отель со своей АСУ

При заселении — POST /residents, при выезде — DELETE /residents/{id}. Гость входит по фамилии и комнате, ничего запоминать не нужно.

Ресторан: купон прямо из кассы

Гость называет промокод — касса дёргает POST /coupons/redeem и показывает кассиру, что именно даёт купон. Воронка «показано → погашено» считается сама, смотрите её в кабинете.

Сеть: посещаемость в свой BI

Раз в сутки забирайте GET /stats?from=&to= — по всем заведениям сразу, с разбивкой по дням и способам входа. Ключ для этого выпустите только с правом чтения.

Остались вопросы?

Напишите нам в поддержку из личного кабинета — отвечаем по будням. Если нужного метода нет — расскажите свой сценарий, мы приоритизируем API по реальным задачам клиентов.