API для разработчиков
Выдавайте гостям доступ к Wi-Fi прямо из своей системы: оплата в коворкинге, бронь в отеле, регистрация на конференции. Забирайте статистику в свой дашборд и гасите купоны на кассе.
Быстрый старт
Три шага до первого выданного кода Wi-Fi:
- В личном кабинете откройте API (раздел виден владельцу аккаунта) и выпустите ключ с правом «Запись». Секрет показывается один раз — сохраните его.
- Узнайте
place_idсвоего заведения — запросомGET /places. - Выдайте гостю код —
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 /places —
place_id тогда возьмите в кабинете и пропишите в своей системе. Для обычной интеграции берите оба.
И скоуп заведений: ключ можно ограничить одним заведением — тогда он не увидит и не тронет остальные.
Ограничение по IP — включите его
У каждого ключа можно указать список разрешённых адресов (в кабинете, поле «Разрешённые IP»):
одиночные адреса и подсети, например 195.24.67.10, 10.0.0.0/24. Запрос с любого другого
адреса получит 403 ip_not_allowed — даже с правильным ключом.
Журнал и уведомления
Все обращения (включая отказы) пишутся в журнал — он виден в кабинете, в разделе «API»: время, ключ, метод, путь, код ответа, IP. Храним 90 дней. По журналу видно и подбор ключа, и запросы с чужого адреса.
Если ключ впервые использован с нового IP-адреса, владелец аккаунта получает письмо — на случай, если ключ попал не в те руки. Уведомление приходит один раз на каждый новый адрес; на первый (когда вы настраиваете интеграцию) — не приходит. Отключается в разделе «Отчёты».
Формат и ошибки
Успешный ответ всегда в поле data, списки дополнены meta. Ошибка — всегда в поле error:
{
"error": {
"code": "identification_required",
"message": "Гость должен быть идентифицирован: передайте phone (от 10 цифр) либо fio + document.",
"details": { "accepted": ["phone", "fio+document"] }
}
}
Ориентируйтесь на code — он стабилен, на него можно писать логику. message может меняться.
| HTTP | code | Что делать |
|---|---|---|
| 401 | unauthorized, invalid_key | Нет заголовка или ключ отозван. |
| 402 | tariff_required | API доступен на тарифе «Про». |
| 403 | insufficient_scope, place_forbidden, ip_not_allowed | Ключу не хватает права, заведение вне доступа или запрос с неразрешённого IP. |
| 404 | not_found, code_not_found | Объект не найден (или не ваш). |
| 409 | login_taken, already_redeemed, coupon_expired | Конфликт состояния — повтор не поможет. |
| 422 | validation_failed, identification_required | Поправьте тело запроса. |
| 429 | rate_limited | Подождите, см. заголовок Retry-After. |
| 500 | internal_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: так мы ловим случайное переиспользование.
Персональные данные
*********67,
ФИО и документ — как ******, MAC — как **:**:**:**:**:48. Это осознанное решение:
ключ не может «утечь вместе с базой». Полные данные видны только в личном кабинете — там показ защищён
отдельным кодом на почту владельца и пишется в журнал доступа к ПДн.
phone
(от 10 цифр) либо fio + document. Так требует ПП РФ 2606/2607: гость публичного
Wi-Fi должен быть идентифицирован в момент выдачи доступа. Когда код выдаёт ваша система, идентификацию
проводит она — у вас уже есть телефон клиента при оплате или брони. Именно поэтому автоматическая выдача
кодов через API законна, а «пачка анонимных кодов на распечатке» — нет.
Заведения
Заведения, доступные ключу. Отсюда берётся 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, выданный код работать не будет: включите вход по коду в настройках заведения.
Точки доступа
Роутеры заведения и их состояние. Точка 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"
}
]
}
Коды Wi-Fi (ваучеры)
Главный сценарий API: гость оплатил час в коворкинге, забронировал домик, зарегистрировался на конференцию — ваша система выдаёт ему доступ.
| Поле | Тип | Описание |
|---|---|---|
place_id * | int | Заведение (из GET /places). |
valid_to * | date-time | До какого момента действует. |
phone | string | Телефон гостя, от 10 цифр. Обязателен, если нет fio+document. |
fio, document | string | Альтернатива телефону: ФИО и документ. |
type | string | code (по умолчанию) — одна строка, генерируем мы. login_password — свои логин и пароль. |
valid_from | date-time | По умолчанию — сейчас. |
scope | string | client — код действует во всех ваших заведениях. |
limits | object | speed_mbit, minutes_total, minutes_per_day, traffic_mb_total, traffic_mb_per_day. Не передан — действуют лимиты точки. |
email, room | string | Необязательные. |
Фильтры: ?place_id=, ?status=active|expired|blocked, плюс пагинация. Код в списке не возвращается.
Продлить или перекрыть доступ. Блокировка действует немедленно — гостя отключит от сети:
# продлить
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}'
Удалить ваучер и снять доступ.
Проживающие (отели)
Гость отеля входит в Wi-Fi по фамилии латиницей и номеру комнаты — отдельный код не нужен. Заселяйте гостей из своей АСУ этим методом.
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} (досрочно выселить).
Сессии
Подключения гостей. Фильтры: ?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>.
Статистика
Агрегаты за период (по умолчанию 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 } ]
}
}
Купоны
Гашение промокода на кассе. Принимает и уникальный код из пула, и общий промокод акции — кассиру не нужно знать тип. Регистр и дефисы не важны.
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.
Список акций со счётчиками показов и погашений.
Готовые сценарии
Коворкинг: оплатил час — получил код
После успешной оплаты вызовите 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 по реальным задачам клиентов.