Logo MGKEIT

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

Как начать, авторизация, лимиты и подробные описания методов с примерами.

Базовый URL https://api.mgkeit.space, префикс /api/v1.

Начало работы

  1. Запросите одноразовый код при помощи метода POST /auth/request-otp (6 цифр, действует 10 минут).
  2. Код нужен для получения токена при помощи метода POST /auth/verify-otp - в ответ вернётся строка вида mgk_live_....
  3. При использование API передавайте заголовок Authorization: Bearer <token> или X-API-Key: <token>.

Аутентификация

ТелоОписание
Заголовок
Authorization: Bearer mgk_live_... или X-API-Key: mgk_live_...
Scopesread:schedules
Формат ошибок{"error":{"code","message","details","request_id"}}

cURL - при помощи Authorization: Bearer

bash
curl -s "https://api.mgkeit.space/api/v1/auth/me" \
  -H "Authorization: Bearer mgk_live_..."

cURL - при помощи X-API-Key

bash
curl -s "https://api.mgkeit.space/api/v1/auth/me" \
  -H "X-API-Key: mgk_live_..."

Лимиты и кэш

  • С ключом: 100/мин
  • При 429 вернётся заголовок Retry-After
  • /buildings, /groups, /timetable, /replacements отдают ETag и поддерживают If-None-Match

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

json
{
  "error": {
    "code": "invalid_param | rate_limited | "401" | "404" | "500"",
    "message": "Текст ошибки",
    "details": { подробная ошибка },
    "request_id": "94062d0d..."
  }
}
HTTPError CodeКогда
400"400"Неверный/просроченный OTP в /auth/verify-otp
401"401"Недействительный токен
404"404"Ресурс не найден
422invalid_paramОшибка валидации
429rate_limitedПревышен лимит
500"500"Внутренняя ошибка
POST /api/v1/auth/request-otp без авторизации

Отправляет одноразовый код (6 цифр) на указанный Email. Код действует 10 минут.

ОграниченияОписание
Лимит по ключу5 запросов/минуту
Антиспам на адресне чаще 1 запроса/мин. на один Email

Тело запроса

json
{ "email": "you@example.com" }

Ответ (200)

json
{ "status": "ok" }

Ошибки

  • 422 - некорректный Email.
  • 429 - частые запросы (общее 5/мин или чаще 1/мин на один адрес).
  • 500 - внутренняя ошибка.
bash
curl -s -X POST "https://api.mgkeit.space/api/v1/auth/request-otp" \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com"}'
python
import requests
r = requests.post('https://api.mgkeit.space/api/v1/auth/request-otp', json={'email':'you@example.com'})
print(r.json())
POST /api/v1/auth/verify-otp без авторизации

Проверяет OTP и создаёт API-ключ. Возвращает полный токен с префиксом mgk_live_.

ОграниченияОписание
Лимит 10 запросов/час
Срок действия OTP10 минут

Тело запроса

json
{ "email":"you@example.com", "code":"123456" }

Ответ (200)

json
{
  "token": "mgk_live_xxx",
  "token_prefix": "mgk_live_",
  "created_at": "2025-09-07",
  "scopes": ["read:schedules"]
}

Ошибки

  • 400 - неверный/просроченный код.
  • 422 - ошибки валидации тела.
  • 429 - превышен лимит (10/час).
bash
curl -s -X POST "https://api.mgkeit.space/api/v1/auth/verify-otp" \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","code":"123456"}'
python
import requests
r = requests.post('https://api.mgkeit.space/api/v1/auth/verify-otp', json={'email':'you@example.com','code':'123456'})
print(r.json())
POST /api/v1/auth/me без авторизации

Возвращает информацию о текущем API-ключе (владельце и параметрах лимитов).

ОграниченияОписание
ЛимитИндивидуальный для ключа (обычно 100/мин).

Тело запроса

json
{ "TOKEN": "mgk_live_..." }

Ответ (200)

json
{
  "_id": "XXXXXXXXXXXXXXXXXXXXXXX",
  "email": "you@example.com",
  "active": true,
  "scopes": ["read:schedules"],
  "ratelimit": "100/minute",
  "created_at": "2025-09-09T10:00:00+00:00",
  "last_used_at": "2025-09-09T19:05:00+00:00"
}

Ошибки

  • 422 - некорректный Email.
  • 429 - частые запросы (общее 5/мин или чаще 1/мин на один адрес).
  • 500 - внутренняя ошибка.
bash
curl -s -X POST "https://api.mgkeit.space/api/v1/auth/me" \
  -H "Authorization: Bearer mgk_live_xxx" | jq
python
import requests
r = requests.post("https://api.mgkeit.space/api/v1/auth/me", headers={"Authorization": "Bearer mgk_live_xxx"})
print(r.json())
POST /api/v1/buildings Bearer

Возвращает список всех корпусов. Метод поддерживает кэширование по ETag.

  • Аутентификация при помощи заголовока Authorization: Bearer mgk_live_...
  • Кэш с использованием ETag из ответа. Передавайте его в If-None-Match - при отсутствии изменений сервер вернёт 304 Not Modified.
КэшЗаголовки
ETag + 304
ETag , Cache-Control: public, max-age=60 , If-None-Match

cURL

bash
BASE="https://api.mgkeit.space"
TOKEN="mgk_live_xxx"

# Простой запрос
curl -i -X POST "$BASE/api/v1/buildings" \
  -H "Authorization: Bearer $TOKEN"
bash
# Повторный запрос с кэшем:
# Подставьте тот ETag, который вернул сервер ранее.
ETAG="<ETAG_ИЗ_ПРЕДЫДУЩЕГО_ОТВЕТА>"

curl -i -X POST "$BASE/api/v1/buildings" \
  -H "Authorization: Bearer $TOKEN" \
  -H "If-None-Match: $ETAG"   # -> 304 Not Modified, если список не менялся

Ответ (200)

json
{
  "buildings": [
    "Судостроительная",
    "Коломенская",
    "Академика Миллионщикова",
    "Бирюлёво"
  ]
}

Ошибки

  • 401 - отсутствует или неверный Bearer-токен.
  • 422 - некорректное тело запроса (валидация JSON).
  • 304 - данные не изменились (при использовании If-None-Match).
  • 429 - превышен лимит запросов.
POST /api/v1/groups Bearer

Возвращает список всех групп для выбранного корпуса. Метод поддерживает кэширование по ETag

Тело (JSON)ТипОбяз.По умолч.Описание
building string да - Название корпуса. Рекомендуем получать из /api/v1/buildings.
limit int [1-500] нет 100 Размер страницы.
offset int ≥ 0 нет 0 Смещение (для пагинации).
КэшЗаголовки
ETag + 304
ETag , Cache-Control: public, max-age=60 , If-None-Match
При повторном запросе с тем же телом можно отправить If-None-Match - если данные не изменились, придёт 304 Not Modified.

cURL

bash
curl -s -X POST "https://api.mgkeit.space/api/v1/groups" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"building":"Судостроительная","limit":50,"offset":0}' | jq
bash
# Следующая страница
curl -s -X POST "https://api.mgkeit.space/api/v1/groups" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"building":"Судостроительная","limit":50,"offset":50}' | jq
bash
# Повторный запрос с кэшем
curl -i -X POST "https://api.mgkeit.space/api/v1/groups" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -H 'If-None-Match: W/"abc123"' \
  -d '{"building":"Судостроительная","limit":50,"offset":0}'   # -> 304 Not Modified

Ответ (200)

json
{
  "building": "Судостроительная",
  "total": 123,
  "limit": 50,
  "offset": 0,
  "groups": ["1КС-1-11-25", "1ОЗИП-1-11-25 (ОЗФ)", "..."]
}

Ошибки

  • 401 - отсутствует или неверный Bearer-токен.
  • 422 - некорректное тело запроса (валидация JSON).
  • 304 - данные не изменились (при использовании If-None-Match).
  • 429 - превышен лимит запросов.
POST /api/v1/replacements Bearer

Возвращает список замен за указанную дату. Можно дополнительно фильтровать по корпусу и/или группе.

Тело (JSON)ТипОбяз.По умолч.Описание
date string (YYYY-MM-DD) да - Дата замен в формате ISO, например 2025-09-09. Часовой пояс - Europe/Moscow.
building string нет - Фильтр по корпусу. Если не указан - вернутся замены по всем корпусам за дату.
group string нет - Фильтр по группе.
КэшЗаголовки
ETag + 304
ETag , Cache-Control: public, max-age=60 , If-None-Match
При повторном запросе с тем же телом можно отправить If-None-Match - если данные не изменились, придёт 304 Not Modified.

cURL

bash
# Все замены по дате
curl -s -X POST "https://api.mgkeit.space/api/v1/replacements" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"date":"2025-09-09"}' | jq
bash
# Фильтр по корпусу
curl -s -X POST "https://api.mgkeit.space/api/v1/replacements" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"date":"2025-09-09","building":"Академика Миллионщикова"}' | jq
bash
# Фильтр по группе
curl -s -X POST "https://api.mgkeit.space/api/v1/replacements" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"date":"2025-09-09","group":"1ИП-3-25"}' | jq
bash
# Повторный запрос с кэшем
curl -i -X POST "https://api.mgkeit.space/api/v1/replacements" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -H 'If-None-Match: W/"abc123"' \
  -d '{"date":"2025-09-09"}'   # -> 304 Not Modified

Ответ (200)

json
{
  "meta": {
    "version": "1.0",
    "date": "2025-09-09",
    "building": "Академика Миллионщикова",
    "count": 3
  },
  "items": [
    {
      "group": "2ИП-4-24",
      "lessons": [3, 4],
      "teacher_from": "Геворгян А.А.",
      "teacher_to": "Ахмерова Н.Д.",
      "room_schedule": "411",
      "room_replace": null
    },
    {
      "group": "1РКИ-3-25",
      "lessons": [3],
      "teacher_from": "Вакансия",
      "teacher_to": "Мызников В.И.",
      "room_schedule": "320",
      "room_replace": "102"
    },
    {
      "group": "1ИП-6-25",
      "lessons": [5, 6],
      "teacher_from": "Маликова А.Р.",
      "teacher_to": "Горбунов О.В.",
      "room_schedule": "307",
      "room_replace": null
    }
  ]
}

Примечания

  • Совмещение фильтров. Если указаны и building и group - применяются оба фильтра.
  • Нумерация занятий. Поле lessons содержит номера занятий по дню.
  • Кэширование. Ответ кэшируется заголовками ETag/Cache-Control; можно использовать If-None-Match для экономии трафика.

Ошибки

  • 401 - отсутствует или неверный Bearer-токен.
  • 422 - некорректное тело запроса (например, опечатка в ключе date).
  • 304 - данные не изменились (при использовании If-None-Match).
  • 429 - превышен лимит запросов.
POST /api/v1/timetable Bearer

Возвращает расписание группы на выбранный день или на «рабочие» дни корпуса (если день не указан и для корпуса задано ограничение). Парные пары уже объединены и имеют итоговое время в полях start/end.

Тело (JSON)ТипОбяз.По умолч.Описание
group string да - Название группы, например 1ОЗИП-1-11-25 (ОЗФ) или 1КС-1-11-25.
building string нет - Название корпуса, например если одинаковые названия групп встречаются в разных корпусах. Если не указан - выбирается лучший матч автоматически.
week "current"|"even"|"odd" нет "current" Выбранная неделя для отдачи. Текущая, чётная, нечётная
day int (0-5) нет - День недели. 0 - Пн, 1 - Вт, 2 - Ср, 3 - Чт, 4 - Пт, 5 - Сб. Если не указан - вернутся только «разрешённые» дни для корпуса.
КэшЗаголовки
ETag + 304
ETag , Cache-Control: public, max-age=60 , If-None-Match
При повторном запросе с тем же телом можно отправить If-None-Match - если данные не изменились, придёт 304 Not Modified.

cURL

bash
# Минимальный запрос (корпус определится автоматически)
curl -s -X POST "https://api.mgkeit.space/api/v1/timetable" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"group":"1ОЗИП-1-11-25 (ОЗФ)"}' | jq
bash
# С указанием корпуса, недели и дня (среда)
curl -s -X POST "https://api.mgkeit.space/api/v1/timetable" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"group":"1ОЗИП-1-11-25 (ОЗФ)","building":"Академика Миллионщикова","week":"odd","day":2}' | jq
bash
# Повторный запрос с кэшем
curl -i -X POST "https://api.mgkeit.space/api/v1/timetable" \
  -H "Authorization: Bearer mgk_live_xxx" \
  -H "Content-Type: application/json" \
  -H 'If-None-Match: W/"abc123"' \
  -d '{"group":"1ОЗИП-1-11-25 (ОЗФ)","day":2}'   # -> 304 Not Modified

Ответ (200)

json
{
  "meta": {
    "version": "1.0",
    "generated_at": "2025-09-09T19:04:24.941351+00:00",
    "group": "1ОЗИП-1-11-25 (ОЗФ)",
    "building": "Академика Миллионщикова",
    "week": "even",
    "current_week": "even",
    "day_filter": 2
  },
  "data": [
    {
      "day_index": 2,
      "day_name": "Среда",
      "units": [
        {
          "kind": "pair",
          "number": 1,
          "display_number": 1,
          "start": "15:50",
          "end": "17:20",
          "subject": "ОП.02 Информационные технологии / Адаптивные информационные и коммуникационные технологии",
          "teacher": "Вакансия часы ОЗ",
          "room": "академика Миллионщикова. каб: 321",
          "subgroup": "",
          "source": "base"
        },
        {
          "kind": "pair",
          "number": 2,
          "display_number": 2,
          "start": "17:30",
          "end": "19:00",
          "subject": "ОГСЭ.02 История",
          "teacher": "Вакансия часы ОЗ",
          "room": "академика Миллионщикова. каб: 305",
          "subgroup": "",
          "source": "base"
        }
      ]
    }
  ]
}

Как выбирается корпус и день

  • Группа. Ищем строгое совпадение с припиской в скобках, затем «база+приписка», затем «база без приписки». Если задан building, он учитывается в поиске.
  • Корпус. Если building не указан, выбирается документ с непустым корпусом и самой поздней датой обновления.
  • Дни. Если day не указан, возвращаются только «разрешённые» дни для выбранного корпуса.
  • Склейка пар. Две соседние одинаковые записи (предмет/преподаватель/аудитория/подгруппа) объединяются в kind="pair" с суммарным временем.

Ошибки

  • 401 - отсутствует или неверный Bearer-токен.
  • 422 - некорректное тело запроса (валидация JSON).
  • 304 - данные не изменились (при использовании If-None-Match).
  • 429 - превышен лимит запросов.