Skip to main content

Reporting

Krios ships a Reports admin surface (/admin/projects/{slug}/reports) with five built-in operational reports, a Governance tab, and a custom-report builder. Every report reads through the tenant + project-scoped client and requires only the read permission. The reports are consumed by the admin UI (charts via Recharts); each is also a plain GET endpoint you can call directly.

Built-in reports

All paths are prefixed /api/v1/projects/{slug}/reports.

Publishing activity — GET /publishing-activity

A time series of publish events plus a recent-events table. Query params: from/to (ISO; default last 30 days), granularity (day | week | month, default day), and optional type, site, locale, user filters. Built from entry.published audit events.

{ "data": {
"buckets": [ { "date": "2026-06-01", "count": 12 } ],
"table": [ { "entryId": "ckl_…", "title": "…", "contentTypeApiName": "articlePage",
"locale": "en-US", "userEmail": "…", "publishedAt": "…" } ],
"meta": { "from": "…", "to": "…", "granularity": "day", "totalPublishes": 142 }
} }

Content health — GET /content-health

Scans every entry in the active environment and surfaces issues per entry. Detects: draft / published / modified (unpublished edits), missing {locale}, stale {locale} (translation out of date), aging draft (draft-only, untouched 30+ days), and broken ref / unpublished ref.

{ "data": {
"summary": { "total": 320, "draft": 40, "published": 270, "modified": 10,
"missingPerLocale": { "fr-CA": 18 }, "staleCount": 7, "agingDraft": 3 },
"rows": [ { "entryId": "…", "title": "…", "contentTypeApiName": "articlePage",
"issues": ["aging draft","missing fr-CA"], "score": 2, "updatedAt": "…" } ]
} }

rows lists only entries with at least one issue, worst-first (score = issue count), capped at 250.

Schema usage — GET /schema-usage

Per-content-type adoption: entry count, field count, last-entry timestamp, and isUnused / hasNoFields flags — useful for spotting dead types before a cleanup.

{ "data": {
"rows": [ { "apiName": "articlePage", "name": "Article Page", "entryCount": 84,
"fieldCount": 6, "lastEntryAt": "…", "isUnused": false, "hasNoFields": false } ],
"summary": { "totalTypes": 14, "unusedTypes": 2, "typesWithoutFields": 0 }
} }

User activity — GET /user-activity

Per-user authoring activity (created / published / updated counts + a weekly series). Params: from/to (default last 90 days), optional role. Built from entry.created / entry.published / entry.updated audit events; roles resolved from project role assignments.

Agent activity — GET /agent-activity

The same shape as user activity, but attributed by API key — any mutation carrying an apiKeyId counts as an agent action, everything else as human. The summary includes agentSharePct so you can see how much of your content is being authored by agents (MCP clients, CI, SDK scripts).

{ "data": {
"rows": [ { "apiKeyId": "…", "name": "CI deploy key", "type": "management", "keyPrefix": "krios_mk",
"created": 30, "published": 12, "total": 42, "lastActive": "…" } ],
"summary": { "agentEvents": 42, "humanEvents": 98, "totalEvents": 140, "agentSharePct": 30 }
} }

Every built-in report has an Export CSV button in the admin UI (client-side download of the table rows).

Governance

The Governance tab runs the governance analyzer — eight detectors (skipped workflow, stale content, aging drafts, broken/unpublished references, translation gaps, orphaned media, unused content types) whose cached GovernanceIssue results you can filter by severity and mark resolved. It uses the governance/analyze, governance/issues, and governance/issues/{id}/resolve endpoints rather than the reports/* endpoints.

Custom reports

Build your own report definition with /custom-reports (CRUD). A report's config selects a data source (entries | auditLogs | translations | media), a set of columns, a chart type (table | bar | line | pie), and optionally filters and an email schedule (the JSON supports both; the current builder UI exposes data source, columns, chart type, and sharing).

POST /api/v1/projects/{slug}/custom-reports
{
"name": "Stale French articles",
"config": {
"dataSource": "translations",
"columns": ["entryId", "locale", "status", "isStale", "updatedAt"],
"chartType": "table"
},
"isShared": false
}
  • Visibility mirrors saved views: you see your own reports plus any isShared: true; only the creator can edit or delete (403 report_not_owned). Creating a report requires a signed-in session (401 session_required for API-key callers).
  • Export: the JSON button exports the report definition; the PDF button uses the browser's print-to-PDF. (Running a saved custom report server-side and exporting its row data is on the roadmap.)

Lineage: the built-in reports and Governance tab arrived in the V3.7 wave; custom reports in V3.8 — all shipped.