SecurityFlow Кабинет лицензий , откроется в новой вкладке

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

API Core

Обновлено 20 октября 2026

Через API Core доступно всё, что делает интерфейс: продукты, ассеты, уязвимости, аудиты, запуск сканов, настройки. Источник истины по методам и полям - спецификация OpenAPI в самом Core. Эта страница - введение: адрес, аутентификация, общие правила и ключевые сценарии.

Базовый адрес и версия

  • Базовый путь: https://core.example.ru/api/v1/. Других версий API нет.
  • Формат - JSON. Исключение - приём отчётов POST /api/v1/scan/import/: multipart/form-data.
  • Пути заканчиваются слешем: /api/v1/findings/, а не /api/v1/findings.
  • Проверка живости без аутентификации: GET /healthcheck/ на порту 8000 процесса API - пустой ответ 200, см. Мониторинг и журналы.

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

API принимает API-токен пользователя в заголовке:

Authorization: Token <токен>
  • Токен один на пользователя и действует до ротации.
  • Получить: "Профиль" → "Токен аутентификации API" или GET /api/v1/profile/auth-token/. Нужна роль с правом "API токен" - "Просмотр".
  • Ротировать: кнопка "Ротировать" там же или GET /api/v1/profile/auth-token/rotate/. Нужно "API токен" - "Изменение". Старый токен перестаёт действовать сразу.
  • Запросы выполняются с правами владельца токена: его ролями и областью продуктов, см. Роли и права.
  • Заголовок Authorization: Bearer ... Core не принимает - ответ 401. Интерфейс Core работает на JWT в cookie, для интеграций используйте только Token.

Отдельный пользователь для интеграций

Для CI и скриптов заведите сервисного пользователя с минимальной ролью под задачу. Пример роли для CI - Security checker.

Спецификация OpenAPI

Что Путь
Swagger UI /api/v1/docs/
ReDoc /api/v1/redoc/
Схема JSON /api/v1/docs.json
Схема YAML /api/v1/docs.yaml

Спецификация - Swagger 2.0, заголовок "Core API". Ссылка "Swagger" есть в профиле пользователя. Откройте её в браузере, где вы вошли в Core.

Права и лицензия

  • Чтение (GET) требует права роли на уровне "Просмотр", запись - "Изменение". Право зависит от раздела: "Продукты", "Уязвимости", "Radar", "Глобальные настройки" и другие.
  • Без активированной лицензии - ответ 419 NO_LICENSE.
  • Платные функции без платной лицензии - 403 Paid feature only.. Методы Radar открыты лицензиям с доступом к Radar. Подробно - Лицензирование.

Пагинация и фильтры

Списки делятся на страницы по 24 элемента. Номер страницы - ?page=N. Размер страницы не настраивается.

{
  "next": 2,
  "previous": null,
  "current": 1,
  "count": 57,
  "pages_count": 3,
  "results": [ ... ]
}
  • next и previous - номера соседних страниц или null.
  • Часть списков (уязвимости, ассеты, продукты, аудиты) принимает ?slice_indexes=<начало>,<конец> - срез выборки, границы включительно.
  • Фильтры - query-параметры с суффиксами Django: __exact, __in, __icontains. Например severity__in=3,4, repository__exact=.... Полный список фильтров метода - в Swagger.
  • Поиск по тексту - ?search=....

Коды, которые встречаются в фильтрах:

Справочник Коды
Критичность (severity) 0 "Инфо", 1 "Низкая", 2 "Средняя", 3 "Высокая", 4 "Критичная"
Статус (triage_status__in) 0 "Решено", 1 "Не обработано", 2 "В работе", 3 "Назначено", 4 "Отклонено", 5 "Временно принят риск", 6 "Постоянно принят риск"
Тип ассета (asset_type) 0 "Репозиторий", 1 "Docker-образ", 2 "Домен", 3 "Хост", 4 "Облачный аккаунт"

Ключевые методы

Префикс /api/v1/ опущен.

Метод Путь Назначение
GET profile/ текущий пользователь и его роли
GET profile/auth-token/ свой API-токен
GET profile/auth-token/rotate/ ротировать свой токен
GET, POST, PATCH, DELETE products/ продукты
GET, POST, PATCH, DELETE product-type/ типы продуктов, без пагинации
GET, POST, PATCH, DELETE product-assets/ ассеты
GET findings/ список уязвимостей с фильтрами
GET findings/{id}/ уязвимость
POST findings/{id}/set-status/{статус}/ сменить статус уязвимости
POST findings/bulk/set-status/{статус}/ сменить статус выборки, заданной фильтрами
GET findings/counters/triage-status/ число уязвимостей по статусам для выборки
GET, POST findings/{id}/comments/ комментарии
POST scan/import/ загрузить отчёт сканера, см. Загрузка отчётов из CI
GET scanners/ сканеры и их импортёры
GET, DELETE audit/, audit/{id}/ аудиты и их итоги по сканерам
POST ci/pipelines/run/ запустить аудит продуктов в Radar
POST products/bulk/run-audit/, product-assets/bulk/run-audit/ запустить аудит продуктов или ассетов, выбранных фильтрами
GET, POST, PATCH, DELETE job-sequences/, jobs/ последовательности и джобы в них
GET, POST, PATCH, DELETE ci/schedules/ расписания сканов
GET ci/health-check/ связь Core с Radar: is_healthy, is_authenticated
GET, POST, PATCH, DELETE quality-gate/ контроль качества
GET license/ данные лицензии
GET celery/tasks/active/ активные фоновые задачи

Массовые методы - всегда с фильтром

Массовые методы .../bulk/... выбирают объекты по query-фильтрам. Всегда передавайте фильтр: например, products/bulk/run-audit/ без фильтров запустит аудит всех продуктов, доступных роли. Для конкретных продуктов используйте ci/pipelines/run/.

Статус в set-status - код или имя: resolved, unverified, verified, rejected, risk_accepted_temporarily, risk_accepted_permanently. Статус "Назначено" Core выставляет сам по данным Jira, когда у задачи уязвимости есть исполнитель.

Сценарии

Проверить токен

curl -s "https://core.example.ru/api/v1/profile/" \
  -H "Authorization: Token <токен>"

Ответ 200 с данными пользователя (сокращено):

{
  "id": 7,
  "username": "ci",
  "email": "ci@example.ru",
  "roles": [ ... ]
}

401 - токен неверный. 419 - в Core не активирована лицензия.

Найти открытые критичные уязвимости репозитория

Статусы 1-3 - неразобранные, критичность 3-4 - "Высокая" и "Критичная".

curl -s -G "https://core.example.ru/api/v1/findings/" \
  -H "Authorization: Token <токен>" \
  --data-urlencode "repository__exact=git@gitlab.example.ru:team/payments.git" \
  --data-urlencode "branch__exact=main" \
  --data-urlencode "severity__in=3,4" \
  --data-urlencode "triage_status__in=1,2,3" \
  --data-urlencode "page=1"

Ответ 200 (сокращено):

{
  "next": null,
  "previous": null,
  "current": 1,
  "count": 1,
  "pages_count": 1,
  "results": [
    {
      "id": 4811,
      "name": "Hard-coded password",
      "severity": 3,
      "current_sla_level": 1,
      "product": 7,
      "file_path": "app/settings.py",
      "line": 42,
      "repository": "git@gitlab.example.ru:team/payments.git",
      "branch": "main",
      "sla_violated": false
    }
  ]
}

current_sla_level - код статуса уязвимости.

Посчитать уязвимости по статусам для проверки в CI

curl -s -G "https://core.example.ru/api/v1/findings/counters/triage-status/" \
  -H "Authorization: Token <токен>" \
  --data-urlencode "repository__exact=git@gitlab.example.ru:team/payments.git" \
  --data-urlencode "branch__exact=main" \
  --data-urlencode "severity__in=3,4"
{"0": 12, "1": 0, "2": 2, "3": 1, "4": 3, "5": 0, "6": 0}

Ключи - коды статусов. Сумма ключей 1, 2 и 3 - неразобранные уязвимости.

Отклонить уязвимость или временно принять риск

curl -s -X POST "https://core.example.ru/api/v1/findings/4811/set-status/rejected/" \
  -H "Authorization: Token <токен>"

curl -s -X POST "https://core.example.ru/api/v1/findings/4811/set-status/risk_accepted_temporarily/" \
  -H "Authorization: Token <токен>" \
  -H "Content-Type: application/json" \
  -d '{"accept_duration_days": 14}'
  • Ответ 200 - уязвимость в новом статусе.
  • Тот же статус повторно - 409 Finding already has status ....
  • accept_duration_days - срок временного принятия риска в днях, не меньше 1.

Смена статуса запускает те же действия, что в интерфейсе: задачи Jira, уведомления. Подробно - Жизненный цикл уязвимости.

Запустить аудит продукта

curl -s -X POST "https://core.example.ru/api/v1/ci/pipelines/run/" \
  -H "Authorization: Token <токен>" \
  -H "Content-Type: application/json" \
  -d '{"products": [7], "branch": "main", "job_sequence": 2}'
Поле Обязательное Описание
products да id продуктов. Сканируются все их ассеты
branch нет ветка для ассетов-репозиториев, до 100 символов
job_sequence нет id последовательности. Не задан - последовательность ассета или по умолчанию
exclude_asset_ids нет id ассетов, которые не сканировать. Не передавайте пустой список

Ответ 202 без тела. Аудиты создаются в фоне, по одному на ассет. Нужны право "Radar" - "Изменение" и лицензия с доступом к Radar.

Асинхронные операции

Ответ 202 значит "принято в работу", результат появляется позже:

Операция Как узнать результат
POST scan/import/ GET audit/{audit_id}/: в scanners появится запись сканера
POST ci/pipelines/run/, POST products/bulk/run-audit/ аудиты в GET audit/, пайплайны - в Radar
POST findings/bulk/set-status/{статус}/ для выборки больше 24 уязвимостей ответ 202 с телом []; статусы меняются в фоне, проверьте повторным запросом списка

Коды ответа

Код Когда Что делать
200 успех -
201 объект создан -
202 операция принята в фоновую обработку проверьте результат, см. выше
204 объект удалён -
400 ошибка в данных: {"поле": ["текст"]} или {"detail": "текст"} исправьте запрос по тексту ошибки
401 нет заголовка Authorization: Token, токен неверный или ротирован проверьте токен и схему Token
403 у роли нет права; функция платная (Paid feature only.); подпись лицензии не прошла проверку или срок истёк проверьте роль и лицензию
404 объект не найден или вне области продуктов роли; номер страницы больше последней проверьте id и область роли
409 конфликт: статус уже установлен, продукт с таким именем и типом существует -
419 лицензия не активирована: {"detail": "NO_LICENSE"} активируйте лицензию, см. Активация лицензии в Core
420 POST license/activate/, а лицензия уже активирована замените лицензию через POST license/
500 внутренняя ошибка журнал бэкенда Core: поды из образа sf-core-back

После 403 из-за неверной подписи или истёкшего срока Core удаляет лицензию, и следующие запросы получают 419.