13 KiB
13 KiB
Технический проект. Документ 2: Контракты API (REST)
Проект: АС «Платформа ОПОРА РОССИИ» Стек: FastAPI, единое API для бота и сайта Дата: 26.09.2026 Статус: черновик к согласованию
1. Общие принципы
- Base URL:
https://opora.my-dpr.ru/api/v1 - Формат: JSON (
application/json), файлы —multipart/form-data. - Аутентификация:
Authorization: Bearer <JWT>(сессия после входа через бота). - Версионирование: префикс
/v1. - Пагинация:
?page=1&per_page=50→ ответ{ items, total, page, per_page }. - Сортировка/фильтры:
?sort=-created_at®ion_id=12&status=new. - Идемпотентность: заголовок
Idempotency-Keyдля POST, создающих сущности. - Время: ISO 8601 UTC (
2026-09-26T12:00:00Z).
Формат ошибки
{
"error": {
"code": "validation_error",
"message": "Поле due_date обязательно",
"details": { "field": "due_date" }
}
}
Коды ответов
| Код | Значение |
|---|---|
| 200 | OK |
| 201 | Создано |
| 204 | Удалено (без тела) |
| 400 | Некорректный запрос |
| 401 | Не авторизован |
| 403 | Нет прав |
| 404 | Не найдено |
| 409 | Конфликт (например, ссылка уже использована) |
| 422 | Ошибка валидации |
| 429 | Превышен лимит запросов |
| 500 | Внутренняя ошибка |
2. Аутентификация
2.1. POST /auth/login-token — выдать одноразовую ссылку (координатор)
Права: coordinator, admin.
// request
{ "region_id": 12, "user_id": null, "ttl_minutes": 60 }
// response 201
{ "id": "uuid", "url": "https://opora.my-dpr.ru/login?token=...", "expires_at": "..." }
2.2. POST /auth/login — вход по одноразовой ссылке
// request
{ "token": "...", "messenger_type": "telegram", "messenger_id": "123456" }
// response 200
{ "access_token": "jwt", "expires_at": "...", "user": { "id": 1, "full_name": "..." } }
Ошибки: 409 link_already_used → «Ссылка уже была использована. Запросите новую у координатора».
2.3. POST /auth/logout — завершить сессию
2.4. GET /auth/me — текущий пользователь
{
"id": 1, "full_name": "Иванов И.И.", "member_type": "member",
"regions": [{ "id": 12, "name": "ДНР", "is_primary": true }],
"roles": [{ "code": "region_head", "region_id": 12 }]
}
3. Регионы и карточка
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /regions |
авторизован | список регионов (фильтр по округу) |
| GET | /regions/{id} |
авторизован | регион |
| GET | /regions/{id}/card |
авторизован | карточка региона |
| PATCH | /regions/{id}/card |
region_head (своё), admin | обновить карточку |
| GET | /regions/{id}/links |
авторизован | ссылки на сообщества/чаты |
| POST | /regions/{id}/links |
region_head (своё), admin | добавить ссылку |
| PATCH | /regions/{id}/links/{linkId} |
region_head (своё), admin | изменить |
| DELETE | /regions/{id}/links/{linkId} |
region_head (своё), admin | удалить |
| GET | /regions/{id}/members |
авторизован | члены региона |
| GET | /regions/{id}/history |
авторизован | история изменений карточки |
Пример GET /regions/12/card:
{
"region": { "id": 12, "name": "Донецкая Народная Республика", "district": "ЮФО" },
"population": 1200,
"members_count": 340,
"residents_count": 45,
"head": { "id": 5, "full_name": "..." },
"links": [{ "id": 1, "type": "chat", "title": "Чат ДНР", "url": "..." }],
"updated_at": "..."
}
4. Цели и метрики
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /goals |
авторизован | список целей |
| GET | /goals/{id} |
авторизован | цель |
| GET | /goals/{id}/metrics |
авторизован | метрики по цели (регионы/округа) |
| GET | /metrics/regions |
авторизован | метрики по регионам |
| GET | /metrics/districts |
авторизован | агрегаты по округам |
| GET | /metrics/ratings |
авторизован | рейтинг регионов |
| GET | /metrics/red-zone |
авторизован | регионы без прироста |
| POST | /uploads |
admin | загрузить выгрузку |
| GET | /uploads |
admin | список выгрузок |
Пример GET /goals/1/metrics:
{
"goal": { "id": 1, "name": "Рост базы членов", "target_value": 1096 },
"point0": { "date": "2026-05-08", "value": 1000 },
"current": { "date": "2026-08-07", "value": 1338 },
"growth": 338,
"districts": [
{ "id": 1, "name": "ЮФО", "growth": 365, "regions_with_dynamics": 12, "regions_total": 12 }
],
"freshness_days": 3,
"auto_update": true
}
Пример GET /metrics/ratings?sort=-growth:
{
"items": [
{ "region_id": 77, "name": "Москва", "growth": 224, "has_dynamics": true },
{ "region_id": 2, "name": "Башкортостан", "growth": 217, "has_dynamics": true }
],
"total": 89
}
5. Задачи (трекер)
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /tasks |
авторизован | список (фильтры: мои, регион, просроченные) |
| POST | /tasks |
авторизован | создать |
| GET | /tasks/{id} |
авторизован | задача |
| PATCH | /tasks/{id} |
автор/исполнитель/admin | изменить (в т.ч. статус) |
| DELETE | /tasks/{id} |
автор/admin | удалить (мягко) |
| GET | /tasks/{id}/comments |
авторизован | комментарии |
| POST | /tasks/{id}/comments |
авторизован | добавить комментарий |
Пример POST /tasks:
// request
{
"title": "Подготовить отчёт по приросту",
"description": "...",
"due_date": "2026-10-01",
"priority": "high",
"region_id": 12,
"assignee_user_id": 5
}
// response 201
{ "id": 101, "status": "new", "created_at": "..." }
Статусы: new → in_progress → review → done.
6. Артефакты
| Метод | Путь | Права | Описание |
|---|---|---|---|
| POST | /artifacts |
авторизован | загрузить файл (multipart) |
| GET | /artifacts |
авторизован | список (фильтр по региону/цели/задаче) |
| GET | /artifacts/{id} |
авторизован | метаданные |
| GET | /artifacts/{id}/download |
авторизован | скачать (presigned URL) |
| DELETE | /artifacts/{id} |
автор/admin | удалить |
Ограничения: до 50 МБ, типы: изображения, PDF, DOCX, XLSX (п. 4.2.8.1 ТЗ).
7. База знаний
| Метод | Путь | Права |
|---|---|---|
| GET | /knowledge/articles |
авторизован |
| GET | /knowledge/articles/{id} |
авторизован |
| GET | /knowledge/categories |
авторизован |
8. Календарь событий
| Метод | Путь | Права |
|---|---|---|
| GET | /events |
авторизован |
| GET | /events/{id} |
авторизован |
| POST | /events/{id}/reminders |
авторизован |
9. Запросы (заявки)
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /requests |
авторизован | список (свои / по региону / все для admin) |
| POST | /requests |
авторизован | создать заявку |
| GET | /requests/{id} |
авторизован | заявка |
| PATCH | /requests/{id} |
admin/coordinator | изменить статус |
| POST | /requests/{id}/comments |
авторизован | комментарий |
Типы: join, access, event, support.
10. Советы от регионов
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /advices |
авторизован | список (публичные) |
| POST | /advices |
region_head (при наличии динамики) | опубликовать совет |
| PATCH | /advices/{id} |
автор/admin | скрыть/изменить |
11. Рассылки (администрирование)
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /broadcasts |
admin | список |
| POST | /broadcasts |
admin | создать (из шаблона) |
| GET | /broadcasts/{id} |
admin | статус и прогресс |
| POST | /broadcasts/{id}/send |
admin | запустить |
| GET | /broadcast-templates |
admin | шаблоны |
| PATCH | /broadcast-templates/{id} |
admin | редактировать текст |
Пример GET /broadcasts/5:
{
"id": 5, "type": "rating", "status": "sending",
"total": 10000, "sent": 4200, "failed": 12,
"started_at": "...", "finished_at": null
}
12. История платформы
| Метод | Путь | Права |
|---|---|---|
| GET | /history |
авторизован (публичная лента) |
13. Ассистент «Зам»
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /assistant/config |
владелец | настройки ассистента |
| PATCH | /assistant/config |
владелец | включить/ограничить |
| GET | /assistant/actions |
владелец | журнал действий ассистента |
Пример PATCH /assistant/config:
{ "enabled": true, "permissions": { "publish": true, "delete": false } }
14. Администрирование
| Метод | Путь | Права | Описание |
|---|---|---|---|
| GET | /users |
admin | список пользователей |
| PATCH | /users/{id} |
admin | изменить (роль, статус, регион) |
| POST | /users/{id}/roles |
admin | выдать роль |
| DELETE | /users/{id}/roles/{roleId} |
admin | отозвать роль |
| GET | /audit |
admin | журнал аудита |
15. Взаимодействие с ботом
Бот использует то же API (сервисный токен) для:
- выдачи одноразовых ссылок (
POST /auth/login-token); - подтверждения входа;
- отправки рассылок (через Celery, не напрямую);
- команд
/start,/login,/requests,/regions,/goals,/events,/help.
Внутренний webhook бота: POST /internal/bot/telegram и POST /internal/bot/max (проверка подписи, только localhost).
16. Ограничения и лимиты
| Область | Лимит |
|---|---|
| Аутентификация | 10 запросов/мин на IP |
| Общие запросы | 100 запросов/мин на пользователя |
| Загрузка файлов | 50 МБ, 20 файлов/час |
| Рассылки | батчами, не более 30 сообщений/сек на канал |
17. Открытые вопросы
- Формат JWT — срок жизни access-токена и нужен ли refresh.
- Сервисный токен бота — отдельный тип или роль
system. - Presigned URL — срок жизни ссылок на скачивание артефактов.
- Вебхуки MAX — уточнить после проверки MAX Bot API.
18. Следующий документ
- Документ 3: макеты экранов (mobile-first).