Skip to content

Обзор API ​

Kvalli предоставляет REST API для CI-пайплайнов, скриптов и дашбордов. Всё, что делает веб-интерфейс, проходит через эти эндпоинты; ничего не зарезервировано только для него.

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

Запрос не из браузера аутентифицируется API-ключом:

  • Authorization: Bearer <KEY>
  • или x-api-key: <KEY>

Ключ принадлежит одному проекту. Ключи создаются через POST /api/apikeys или в разделе «Настройки → API-ключи» (модуль ci, тариф Pro и выше — см. Модули и тарифы). У ключа есть scopes; по умолчанию это testrun:write (он даёт runs:import: отправку отчёта и его файлов, и больше ничего) и cases:read. Ключи хранятся как хеши SHA-256: ключ показывается один раз, при создании, и прочитать его позже нельзя.

Запросы из браузера вместо ключа используют cookie сессии; каждый запрос, меняющий состояние, проходит проверку заголовка Origin.

Подробнее о ключах — в разделе Проекты и администрирование.

Выбор проекта ​

В одной установке может быть несколько проектов. Каждый запрос указывает, к какому проекту он относится:

  • X-Project-Id: <project id or key> (или ?projectId=)

Без него используется текущий проект вызывающего. Сервер при каждом запросе сверяет названный проект с членством вызывающего в проектах: проект, который назвал клиент, — это заявка, а не разрешение.

Ограничения частоты запросов ​

  • Общий API: 300 запросов в минуту (/api/*) на каждую сессию или API-ключ с одного адреса, так что команда за одним NAT-адресом не делит одну квоту; 3000 в минуту на адрес в целом.
  • ИИ и вычисления: 60 запросов в минуту на каждую учётную запись или API-ключ, с какого бы адреса они ни приходили; по адресу считаются только запросы без учётной записи (открытый или демо-режим). Лимит распространяется на весь /api/ai/* при любом методе, на POST /api/reports/generate и на все запросы, кроме GET, под /api/agents, /api/workflows и /api/chat: чтение воркфлоу или беседы не ограничено, а запуск воркфлоу или отправка сообщения — ограничены. POST /api/regression/suggest тоже обращается к модели, но подпадает только под общий лимит.
  • Репозиторий: 60 запросов в минуту (/api/repo/*).
  • Вход: 10 попыток ввода пароля на учётную запись и адрес, 300 на адрес, за 15 минут (/api/auth/login); 20 смен пароля за 15 минут.
  • Публичные страницы отчётов: 120 в минуту (/share/*).
  • Задачи агентов: не больше 3 одновременно на проект — см. ИИ-агенты.

Счётчики ведутся в каждом процессе сервера отдельно.

Ошибки ​

Отказ говорит, что исправить: 400 с сообщением по каждому полю, 403 с названием недостающего права, 409 с текущей версией на сервере. Сбой сервера (5xx) называет только операцию, которая не удалась, и содержит requestId — тот же id, что приходит в заголовке X-Request-Id; сама ошибка записана в журнал сервера под этим id.

Маршрут модуля, на который у установки нет лицензии, отвечает 403 с названием модуля:

json
403 { "error": "This installation is not licensed for Agents & Chat.", "module": "agents", "code": "module_not_licensed" }

Модули и тарифы ​

Лицензия определяет, какие части API подключены (подробнее — Лицензия и Тарифы и модули). Тарифы накопительные: Starter (без ключа, 1 проект, 5 пользователей) включает repository и runs; Pro добавляет analytics, agents и ci; Enterprise добавляет sso, operations, healing и eval. Поле features ключа может добавить к тарифу отдельный модуль. Нелицензированный модуль отклоняется, как показано выше, и скрыт в интерфейсе; ничего не удаляется. GET /api/auth/me перечисляет лицензированные модули в modules.

ПрефиксМодульТариф
всё, что не перечислено ниже (кейсы, папки, общие шаги, поля, требования, тест-планы, прогоны, майлстоуны, конфигурации, сессии, дефекты, проекты, пользователи, настройки, лицензия)repository, runsStarter
/api/analytics, /api/reportsanalyticsPro
/api/agents, /api/chat, /api/workflows, /api/ai, /api/repo, /api/regression, /api/sources, /api/swagger, /api/confluence, /api/task-manager, /api/requirements-bundle, /api/contracts, /api/config/test-confluence, /api/admin/usageagentsPro
/api/pipelines, /api/apikeysciPro
/api/auth/oidcssoEnterprise
/api/admin/system, /api/admin/audit (/api/admin/telemetry доступен на всех тарифах начиная с 2.0.1)operationsEnterprise
/api/healinghealingEnterprise
/api/agents/eval, /api/agents/skills/eval-testevalEnterprise

В локально собранный образ не вшит публичный ключ лицензии: он работает как Starter и не принимает ключ. Опубликованные образы проверяют ключи. Редакция Starter (ghcr.io/kvalli-ai/kvalli-starter) не содержит кода платных модулей, поэтому использует только repository и runs, что бы ни давал ключ. GET /api/admin/license сообщает об этом (edition: "starter"), а маршрут платного модуля отвечает тем же 403 с тем же кодом, но говорит, что модуля нет в редакции Starter (а не что он не лицензирован), и добавляет "edition": "starter". Полная редакция — ghcr.io/kvalli-ai/kvalli.

Одновременное редактирование (версии) ​

Всё, что люди редактируют параллельно, несёт поле version — счётчик изменений записи — в каждом ответе, который её возвращает (списки, чтение и ответ на сохранение, в котором уже новая версия). Обновление отправляет обратно version, на основе которой оно сделано; сервер записывает его, только пока запись всё ещё в этой версии, а иначе отвечает

json
409 { "error": "…was changed by someone else…", "code": "version_conflict", "currentVersion": 7 }

Перечитайте запись, примените изменение заново и отправьте новую версию. 409 без code: "version_conflict" — это другой отказ (дублирующееся название, открытые прогоны), и перечитывание его не исправит.

ЗаписьОткуда читать versionКуда отправлять version
Тест-кейс, общий шагсм. Тест-кейсысм. Тест-кейсы (для общего шага обязательно)
Отклонённый кейс несёт serverCase рядом с code и currentVersion: кейс в том виде, в каком сервер его сравнивал, чтобы редактор мог показать версию, из-за которой изменение отклонено, без повторного чтения.
МайлстоунGET /api/milestones[/:key]PUT /api/milestones/:key, POST …/complete, POST …/reopen
Исследовательская сессияGET /api/sessions[/:key]PUT /api/sessions/:key, POST …/complete, POST …/reopen
Заметка сессииnotes[] из GET /api/sessions/:keyPATCH /api/sessions/:key/notes/:noteId
ТребованиеGET /api/requirements[/:key]PUT /api/requirements/:key
Тест-планGET /api/plans[/:key]PUT /api/plans/:key
Поле кейсаGET /api/case-fieldsPUT /api/case-fields/:key
Статус результатаGET /api/result-statusesPUT /api/result-statuses/:key
Группа конфигурацийGET /api/configurationsPUT /api/configurations/:id
ИсточникGET /api/sourcesPUT /api/sources/:id
Сохранённый видGET /api/saved-viewsPUT /api/saved-views/:id
Свой агентGET /api/agents/custom[/:slug]POST /api/agents/custom (сохранение существующего агента)
Навык проектаGET /api/agents/skillsPOST /api/agents/skills с id (правка; обязательно)
Черновик Агента 1GET /api/agents/agent1/draftsPUT /api/agents/agent1/drafts/:id
Настройки установкиGET /api/configPUT /api/config

Изменения, которые только добавляют (POST /api/plans/:key/cases, привязка кейса к требованию, добавление заметки в сессию), не принимают версию и ничего не теряют. Однако добавление кейсов в тест-план всё равно увеличивает его версию, так что редактор, у которого старый список кейсов плана, получит отказ, а не запишет его поверх нового. Сохранения, которые не называют версию (POST /api/sources со всем списком, импорт), увеличивают счётчик так же. Завершение или повторное открытие майлстоуна или сессии — тоже изменение. У встроенного навыка версии нет.

Обновление без version по-прежнему принимается и записывается при любой версии, чтобы API-клиенты, написанные до появления версий, продолжали работать. Так делать не рекомендуется: именно такое сохранение молча затирает чужое изменение. Экраны Kvalli всегда отправляют версию. Обновление, которое называет версию источника, своего агента или навыка, удалённого с тех пор, получает 404; запись при этом не восстанавливается.

Пример: отправка результатов из CI ​

bash
curl -X POST \
  -H "x-api-key: $KVALLI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Project-Id: SHOP" \
  -d @playwright-report.json \
  "https://kvalli.example.com/api/runs/import?environment=staging&release=$CI_COMMIT_REF_NAME"

Готовые клиенты и настройка для разных CI — в разделе Отправка результатов из CI. Подробности маршрута импорта — в разделе Прогоны.

Документация описывает последний выпуск Kvalli.