Skip to content
Exlogare

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 — анализы постоянно добавляются и сдвигают пагинацию.

ПараметрТипОписание
sinceISO 8601 datetimeНижняя граница created_at (включительно). Naive-время трактуется как UTC.
untilISO 8601 datetimeВерхняя граница created_at (включительно). Окно <= 365 дней.
severitylow / medium / highФильтр по severity.
projectstringСравнение с project_path (например, acme/api) или project_id.
sourcestringИсточник: gitlab_webhook, github_poll, circleci_ingest, generic_ingest и т.д.
cursorstringНепрозрачный курсор из предыдущего next_cursor.
limitint1..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.
404id анализа не принадлежит вашему тенанту.
429Rate limit.