Read API (v1)
Версионированный REST API для чтения истории RCA и статистики — для дашбордов, скриптов и ботов.
/api/v1 — стабильный контракт для чтения данных из Exlogare. Используйте его в Grafana, плановых скриптах, Slack/Discord-ботах или везде, где иначе пришлось бы парсить дашборд.
Браузерный /api/analyses не версионируется — он может изменить форму вместе с дашбордом. /api/v1 — это интеграционная поверхность, и мы не будем ломать её без явного периода миграции.
Авторизация
Создайте токен с scope=read в Settings → API tokens (нужна роль admin). На Free-плане доступно до 3 активных токенов; на платных — без ограничений.
curl -H "Authorization: Bearer $EXLOGARE_TOKEN" \
"https://api.exlogare.net/api/v1/analyses?since=2026-04-01"
Для терминала и cron-скриптов есть Exlogare CLI, который использует этот же /api/v1:
exl analyses list --since 2026-04-01T00:00:00Z
exl analyses show <analysis-id>
Токен с scope=ingest получит 403 на этих ручках — это так задумано: утёкший ingest-токен нельзя перепрофилировать на чтение.
Эндпоинты
| Метод | Путь | Что возвращает |
|---|---|---|
GET | /api/v1/analyses | Постраничный список RCA (новые сверху). |
GET | /api/v1/analyses/{id} | Один RCA. |
GET | /api/v1/stats/overview | Счётчики, разбивка по severity, p50/p90 time-to-RCA. |
GET | /api/v1/stats/timeseries | Кол-во падений по дням. |
GET | /api/v1/stats/top-projects | Топ N проектов по числу падений. |
GET | /api/v1/stats/top-root-causes | Топ N кластеров root cause. |
Каждая ручка принимает Bearer exl_…. Заголовок CSRF не нужен — он только для браузерных сессий.
GET /api/v1/analyses
Cursor-пагинация, новые сверху. Используйте курсор, а не offset/limit — анализы постоянно добавляются и сдвигают пагинацию.
| Параметр | Тип | Описание |
|---|---|---|
since | ISO 8601 datetime | Нижняя граница created_at (включительно). Naive-время трактуется как UTC. |
until | ISO 8601 datetime | Верхняя граница created_at (включительно). Окно <= 365 дней. |
severity | low / medium / high | Фильтр по severity. |
project | string | Сравнение с project_path (например, acme/api) или project_id. |
source | string | Источник: gitlab_webhook, github_poll, circleci_ingest, generic_ingest и т.д. |
cursor | string | Непрозрачный курсор из предыдущего next_cursor. |
limit | int | 1..500, по умолчанию 100. |
Ответ:
{
"items": [
{
"id": "39af2c01-...",
"provider": "gitlab",
"source": "gitlab_webhook",
"ci_run_id": "654",
"ci_job_id": "1552",
"project_id": "12345",
"project_path": "apex/apexframework/release-server",
"project_web_url": "https://gitlab.com/apex/apexframework/release-server",
"pipeline_url": "https://gitlab.com/apex/apexframework/release-server/-/pipelines/654",
"job_url": "https://gitlab.com/apex/apexframework/release-server/-/jobs/1552",
"mr_iid": null,
"root_cause": "Connection refused: postgres:5432",
"explanation": "...",
"fix_suggestion": "...",
"severity": "high",
"confidence": 0.87,
"created_at": "2026-04-21T10:15:00Z"
}
],
"next_cursor": "MjAyNi0wNC0yMVQxMDoxNTowMHwzOWFmMmMwMS0...",
"limit": 100
}
Идём по страницам, пока next_cursor не станет null:
cursor=""
while :; do
page=$(curl -fsS -H "Authorization: Bearer $EXLOGARE_TOKEN" \
"https://api.exlogare.net/api/v1/analyses?limit=200${cursor:+&cursor=$cursor}")
echo "$page" | jq -r '.items[] | [.created_at, .severity, .project_path, .root_cause] | @tsv'
cursor=$(echo "$page" | jq -r '.next_cursor // empty')
[ -z "$cursor" ] && break
done
GET /api/v1/analyses/{id}
Возвращает один RCA в той же форме, что элемент items. 404, если id не принадлежит вашему тенанту.
Статистика
Все /api/v1/stats/* принимают days (1..365, по умолчанию 30). У top-projects и top-root-causes есть limit (1..50, по умолчанию 10).
curl -H "Authorization: Bearer $EXLOGARE_TOKEN" \
"https://api.exlogare.net/api/v1/stats/overview?days=7"
{
"failures_detected": 42,
"analyses_completed": 41,
"rca_count": 41,
"severity_counts": {"low": 11, "medium": 18, "high": 12},
"avg_time_to_rca_seconds": 27.4,
"p50_time_to_rca_seconds": 12.0,
"p90_time_to_rca_seconds": 78.1,
"window_days": 7
}
Рецепты
Утренний дайджест в Slack
Положите morning-digest.py в cron / scheduled GitHub Action. Скрипт читает RCA за вчера и шлёт сводку в Slack incoming-webhook. Готовый пример: /integrations/scripts/morning-digest.py.
Если нужен shell-only вариант без Python, используйте CLI:
exl analyses list --since 24h --severity high --json \
| jq -r '.items[] | "[\(.severity)] \(.project_path): \(.root_cause)"'
Дашборд Grafana
У нас есть готовый JSON-дашборд под Infinity datasource: /integrations/grafana/exlogare-rca.json. Импортируйте в Grafana → задайте Bearer-токен → готово. Подробнее в гайде по интеграции с Grafana.
Pull-бот в Slack/Discord
Если ваш бот предпочитает опрашивать сам, а не подписываться на наш fan-out — крутите /api/v1/analyses?since=$LAST_RUN&severity=high раз в 5 минут. Используйте next_cursor, чтобы не пропустить анализы при бэклоге.
Ошибки
| Статус | Что значит |
|---|---|
400 | Невалидный запрос (битый курсор, since > until, окно > 365 дней, неверный severity). |
401 | Нет токена или он отозван. |
403 | У токена нет scope=read. |
404 | id анализа не принадлежит вашему тенанту. |
429 | Rate limit. |