API

Документация API

Интерактивная документация backend:

/api/docs

ReDoc:

/api/redoc

OpenAPI schema:

/api/openapi.json

Общие правила

Префикс

Все backend-ручки доступны под префиксом:

/api/

Форматы запросов

Используются:

  • application/json
  • multipart/form-data

multipart/form-data нужен для загрузки:

  • изображений карты;
  • GeoJSON-файлов.

Авторизация

Поддерживаются два способа:

  • Authorization: Bearer <access_token>
  • HTTP-only cookie, которую backend ставит после логина и регистрации

Лимиты

  • гость: 5
  • авторизованный пользователь: 100

Формат блока лимитов:

{
  "used": 2,
  "limit": 5
}

Endpoint'ы

Auth

POST /api/auth/register

Регистрирует пользователя, создает аккаунт и отправляет письмо подтверждения email.

Принимает:

  • JSON
  • form-data

Поля:

  • login — обязательно
  • email — обязательно
  • password — обязательно
  • user_id — optional

Пример:

{
  "login": "demo_user",
  "email": "demo@example.com",
  "password": "strongpass123"
}

Успех:

{
  "success": true,
  "email_verification_required": true,
  "email_verification_expires_at": "...",
  "email_verification_url": "https://terrai.site/verify-email",
  "message": "Регистрация начата. На email отправлено письмо для подтверждения адреса.",
  "pending_user": {
    "user_id": "...",
    "login": "demo_user",
    "email": "demo@example.com",
    "email_verified": false
  }
}

Типовые ошибки:

  • 400 invalid_login
  • 400 invalid_email
  • 400 invalid_password
  • 409 login_taken
  • 409 email_taken
  • 409 user_id_taken
  • 502 verification_email_send_failed
  • 503 email_delivery_not_configured

POST /api/auth/login

Создает новую пользовательскую сессию.

Можно передавать:

  • identifier + password
  • или login + password
  • или email + password

Пример:

{
  "identifier": "demo@example.com",
  "password": "strongpass123"
}

Типовые ошибки:

  • 400 invalid_request
  • 401 unauthorized
  • 403 user_inactive
  • 403 email_not_verified

GET /api/auth/verify-email?token=...

Backend-ссылка из письма. Подтверждает email по токену, создает сессию и делает redirect на фронтовый /verify-email.

Особенности:

  • endpoint обычно открывается браузером по ссылке из письма;
  • не рендерит отдельную HTML-страницу;
  • после успешного подтверждения ставит auth-cookie;
  • затем делает redirect на фронтовый verify-email с query-параметрами статуса;
  • при успешном подтверждении пользователь авторизуется автоматически.

Типовые статусы:

  • 303 — redirect на фронт с результатом подтверждения

POST /api/auth/resend-verification

Повторно отправляет письмо подтверждения email.

GET /api/auth/verify-email/confirm?token=...

JSON-endpoint для programmatic confirm flow. Используется фронтом как fallback и возвращает либо auth-payload, либо JSON с ошибкой/статусом подтверждения.

Принимает:

  • identifier
  • или login
  • или email

Пример:

{
  "identifier": "demo@example.com"
}

Ответ:

{
  "success": true,
  "email_verification_required": true,
  "email": "demo@example.com",
  "message": "Письмо подтверждения отправлено повторно. Ссылка действует до ..."
}

GET /api/auth/me

Возвращает текущего пользователя.

Требует действующую сессию.

Пример ответа:

{
  "user": {
    "user_id": "...",
    "login": "demo_user",
    "email": "demo@example.com",
    "is_active": true,
    "created_at": "...",
    "updated_at": "...",
    "last_login_at": "..."
  },
  "used": 3,
  "limit": 100
}

POST /api/auth/logout

Закрывает текущую сессию.

Ответ:

{
  "success": true,
  "message": "Выход выполнен."
}

Chat и usage

POST /api/chat

Главный endpoint общения с моделью.

Поддерживает:

  • JSON
  • multipart/form-data

Основные поля:

  • user_id
  • session_id — ID текущей браузерной сессии для контекста чата
  • message
  • answer_type
  • geojson
  • geojson_file
  • image
  • image_user
  • image_esri
  • image_osm

Поддерживаемые режимы answer_type:

  • standard
  • concise
  • tourism
  • research
  • realty

Пример:

{
  "user_id": "guest-123",
  "session_id": "browser-session-123",
  "message": "Что находится в этой точке?",
  "answer_type": "standard"
}

Успешный ответ:

{
  "reply": "Текст ответа модели",
  "used": 1,
  "limit": 5
}

Поведение:

  • если пользователь авторизован, user_id берется из сессии;
  • история чата хранится только в памяти backend для переданного session_id;
  • backend не подгружает и не сохраняет контекст чата в БД;
  • последний выбранный answer_type сохраняется в session state текущего session_id и потом может использоваться для PDF.

Типовые ошибки:

  • invalid_request
  • limit_exceeded
  • ai_error

GET /api/user/{user_id}

Возвращает usage-limit.

Если запрос авторизован, backend использует user из сессии и отдает лимит авторизованного пользователя.

Пример:

{
  "used": 4,
  "limit": 100
}

PDF

GET /api/pdf

Упрощенная генерация PDF через query params.

Поддерживаемые query params:

  • user_id
  • session_id — ID текущей браузерной сессии для связи с контекстом чата
  • message
  • latitude
  • longitude
  • zoom
  • answer_type
  • geojson

Возвращает:

  • application/pdf
  • или JSON-ошибку

POST /api/pdf

Основной endpoint генерации PDF.

Принимает multipart/form-data.

Поля:

  • user_id
  • session_id — ID текущей браузерной сессии для связи с контекстом чата
  • message
  • latitude
  • longitude
  • zoom
  • answer_type
  • geojson
  • geojson_file
  • image
  • image_user
  • image_esri
  • image_osm

Поведение:

  • если пользователь авторизован, user_id берется из сессии;
  • backend использует последний пользовательский вопрос только из истории текущего session_id;
  • backend может использовать последний сохраненный answer_type из текущего session_id, если для PDF он явно не передан;
  • если координаты не переданы, backend пытается определить их из текста или GeoJSON.

Успех:

  • 200 OK
  • Content-Type: application/pdf
  • Content-Disposition: attachment; filename="...pdf"

Типовые ошибки:

  • 400 invalid_request
  • 500 pdf_generation_failed

Layers / GeoJSON

POST /api/layers

Alias:

  • POST /api/geojson

Сохраняет GeoJSON в БД.

Поддерживает:

  • raw JSON
  • JSON-объект с полем geojson
  • multipart/form-data с geojson или geojson_file

Поля:

  • user_id
  • title
  • geojson
  • geojson_file

Если пользователь авторизован, слой привязывается к нему автоматически.

Пример:

{
  "title": "visible map layer",
  "geojson": {
    "type": "FeatureCollection",
    "features": []
  }
}

Успех:

{
  "id": "...",
  "created_at": "...",
  "user_id": "...",
  "title": "visible map layer",
  "type": "FeatureCollection",
  "feature_count": 0,
  "geometry_types": {},
  "bounding_box": null
}

Типовые ошибки:

  • 400 invalid_request
  • 400 invalid_geojson
  • 500 geojson_save_failed

GET /api/layers

Alias:

  • GET /api/geojson

Возвращает список слоев текущего авторизованного пользователя.

Требует авторизацию.

Query params:

  • include_geojson=false
  • limit=100

Пример ответа:

{
  "items": [
    {
      "id": "...",
      "user_id": "...",
      "title": "Мой слой",
      "type": "FeatureCollection",
      "feature_count": 12,
      "geometry_types": {
        "Polygon": 3
      },
      "bounding_box": {
        "min_lat": 55.7,
        "max_lat": 55.8,
        "min_lon": 37.5,
        "max_lon": 37.7,
        "center_lat": 55.75,
        "center_lon": 37.6
      },
      "created_at": "2026-03-29T12:34:56+00:00"
    }
  ],
  "count": 1,
  "user_id": "..."
}

Типовые ошибки:

  • 401 unauthorized
  • 500 geojson_list_failed

DELETE /api/layers/{layer_id}

Удаляет слой.

Поведение:

  • авторизованный пользователь удаляет только свои слои;
  • неавторизованный должен явно передать user_id как query parameter.

Пример:

DELETE /api/layers/11111111-1111-1111-1111-111111111111?user_id=guest-123

Успешный ответ:

{
  "success": true,
  "id": "...",
  "user_id": "...",
  "title": "Layer 1"
}

Типовые ошибки:

  • 400 invalid_layer_id
  • 400 invalid_request
  • 404 layer_not_found
  • 500 geojson_delete_failed

Что использовать на практике

  • для ручного тестирования API: /api/docs
  • для генерации клиента: /api/openapi.json
  • для проектной документации: /docs/