Docs / REST API
REST API
Контур отдаёт /api/*, портал — /api/portal/* и прокси
/api/remote/{serverId}/*. Все защищённые маршруты ждут
Authorization: Bearer <token>.
Авторизация и ошибки
# контур: JWT из /api/auth/login или AUTH_TOKEN напрямую
curl -s localhost:9090/api/health
curl -s -H "Authorization: Bearer $TOKEN" localhost:9090/api/docker/state
# портал: JWT портала
curl -s -H "Authorization: Bearer $PORTAL_TOKEN" localhost:9091/api/portal/inventory
| Ответ | Тело | Что значит |
401 | {"error":"…"} | Нет или истёк токен |
403 | {"code":"section_disabled","section":"…"} | Раздел выключен в настройках |
403 | {"error":"… disabled"} | Возможность запрещена PRIVILEGES |
502 | {"code":"contour_unauthorized"} | Портал не смог авторизоваться в контуре: введите ключ заново |
409 | {"error":"… exists"} | Конфликт: имя проекта или секрета занято |
Auth
| Метод | Путь | Описание |
| GET | /api/auth/status | Состояние входа, features, sections, SSO |
| POST | /api/auth/login | Пароль → access + refresh (5 попыток в минуту с IP) |
| POST | /api/auth/refresh | Обновить access по refresh |
| POST | /api/auth/logout | Отозвать refresh |
| GET | /api/auth/oidc/login | 302 к провайдеру (state, nonce, PKCE) |
| GET | /api/auth/oidc/callback | Callback провайдера → одноразовый cookie → /#/login |
| POST | /api/auth/oidc/session | Обменять cookie на пару JWT |
Граф и Docker
| Метод | Путь | Описание |
| GET | /api/docker/state | Полный снимок состояния |
| GET | /api/docker/graph | Граф для UI |
| GET | /api/docker/graph/ws | WebSocket: diff-обновления |
| GET | /api/docker/time-list | Список срезов |
| GET | /api/docker/history/{timestamp} | Граф среза |
| GET | /api/docker/history/diff | Дифф двух срезов |
| GET | /api/docker/history/logs/{id} | Логи контейнера из среза |
| GET | /api/docker/host-metrics | Таймсерия хоста |
| GET | /api/docker/container-names | Имена контейнеров |
| GET | /api/docker/containers/{id}/inspect | Inspect (с маскированием) |
| GET | /api/docker/containers/{id}/stack | Слои образа и окружение |
| GET | /api/docker/containers/{id}/vulnerabilities | Кэш отчёта Trivy |
| POST | /api/docker/containers/{id}/scan | Запустить скан |
| GET | /api/docker/logs/{id}, /ws | Логи и live-стрим |
| GET | /api/docker/exec/{id}/ws | Терминал (нужен exec) |
| GET | /api/docker/volume-tree/{name} | Дерево файлов тома |
| GET | /api/docker/volume-download/{name} | Том как .tar.gz |
| GET | /api/docker/compose-file/{networkID} | Реконструкция compose |
| GET | /api/docker/compose-service/{containerID} | Compose-сервис контейнера |
| GET | /api/docker/compose/{networkID} | Проект целиком |
Действия с контейнерами
Требуют PRIVILEGES=actions; иначе 403. Контейнер docker-stat защищён от остановки и удаления.
POST /api/docker/containers/{id}/start
POST /api/docker/containers/{id}/stop
POST /api/docker/containers/{id}/restart
POST /api/docker/containers/{id}/pause
POST /api/docker/containers/{id}/unpause
POST /api/docker/containers/{id}/kill
DELETE /api/docker/containers/{id}
Настройки и раскладка
| Метод | Путь | Описание |
| GET / PUT | /api/settings | AI, логи, сбор, retention, уязвимости, бэкапы, алерты, разделы, SSO, deployment (ro) |
| POST | /api/settings/rotate-master-key | {"confirm":"ROTATE"}; новый ключ — один раз в ответе |
| GET / PUT | /api/layout | Позиции и свёрнутые группы |
| GET / POST | /api/layout/presets | Пресеты раскладки |
| PUT / DELETE | /api/layout/presets/{id} | Изменить / удалить пресет |
Секреты
Раздел должен быть включён (secrets_enabled), а push — разрешён PRIVILEGES=exec,push.
| Метод | Путь | Описание |
| GET | /api/secrets | Все секреты (содержимое расшифровано) |
| POST | /api/secrets | project, content, container_names[], file_path, push_mode |
| PUT / DELETE | /api/secrets/{id} | Обновить / удалить |
| GET | /api/secrets/targets | Writable-mount'ы, tmpfs и read-only rootfs по контейнерам |
| POST | /api/secrets/{id}/push | Доставка; в ответе results[] со статусом и текстом ошибки |
Проекты и задачи
| Метод | Путь | Описание |
| GET | /api/projects | Список проектов |
| POST | /api/projects, /upload | Создать из JSON / загрузить файл |
| GET / PUT / DELETE | /api/projects/{name} | Чтение, изменение, удаление |
| GET | /api/projects/{name}/status, /jobs, /graph | Статус, история задач, граф проекта |
| POST | /api/projects/{name}/up, /down, /restart, /pull | Compose-действие как фоновая задача |
| GET | /api/jobs/{id} | Статус и хвост вывода |
| POST | /api/jobs/{id}/cancel | Отменить задачу |
Действия up/down/restart/pull требуют PRIVILEGES=compose.
Бэкапы
| Метод | Путь | Описание |
| GET | /api/backup/status | Размер, каталог, последний архив, готовность restore |
| GET | /api/backup/files | Локальные архивы |
| POST | /api/backup | Создать архив |
| GET | /api/backup/download | Создать и сразу скачать |
| GET / DELETE | /api/backup/files/{name} | Скачать / удалить |
| POST | /api/backup/restore, /files/{name}/restore | {"confirm":"RESTORE"}; 202 + restart_required |
Алерты, события, аудит
| Метод | Путь | Описание |
| GET | /api/alerts/status, /history, /deliveries | Правила, переходы, попытки доставки |
| POST | /api/alerts/test | Тестовый вебхук |
| GET | /api/events | Лента Docker-событий и аудита |
| GET | /api/security/audit | Решения docker-api: allow/deny и мутации |
| GET | /api/host | Хост и нагрузка |
| GET | /api/health, /api/ready, /api/metrics | Liveness, readiness, Prometheus |
| GET | /api/vuln/status | Состояние сканера и базы Trivy |
| GET | /api/ai/status | AI: enabled, model, language |
| POST | /api/ai/analyze | Стрим заключения (text/plain) |
| GET | /api/ai/conclusions | История заключений |
| DELETE | /api/ai/conclusions/{id} | Удалить заключение |
API портала
| Метод | Путь | Описание |
| GET | /api/portal/health | Публичная проверка живости |
| GET | /api/portal/auth/status | Состояние входа и SSO |
| POST | /api/portal/auth/login, /refresh, /logout | Сессия портала |
| GET | /api/portal/auth/oidc/login, /callback | OIDC-флоу |
| POST | /api/portal/auth/oidc/session | Cookie → JWT |
| GET / POST | /api/portal/contours | Контуры (dev/stage/prod) |
| PUT / DELETE | /api/portal/contours/{id} | Изменить / удалить контур |
| GET / POST | /api/portal/servers | Серверы: адрес, контур, токен |
| PUT / DELETE | /api/portal/servers/{id} | Изменить / удалить сервер |
| POST | /api/portal/servers/{id}/check | Проверка доступности и ключа |
| GET | /api/portal/inventory | Контуры, серверы и статусы |
| GET / PUT | /api/portal/settings | AI, SSO, алерты портала |
| GET / POST | /api/portal/ai/* | status, analyze, conclusions |
| GET | /api/portal/alerts/status, /deliveries | Watchdog и доставки |
| POST | /api/portal/alerts/test | Тест канала |
Прокси: /api/remote/{serverId}/api/… — тот же путь контура, но с JWT портала; WebSocket проксируется так же.
Пример
TOKEN="$(curl -s -X POST localhost:9090/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"password":"'"$AUTH_TOKEN"'"}' | jq -r .access_token)"
curl -s -H "Authorization: Bearer $TOKEN" \
localhost:9090/api/docker/state | jq '.containers | length'