Skip to content

Dashboard API

Base path: /api/v1/dashboard

The Dashboard module provides management-facing analytics for a single organisation. All data is strictly scoped to the caller's organisation — org_id is read from the JWT and cannot be overridden by request parameters.

See API Reference for auth, errors, and pagination.

Access: All endpoints require role manager or admin and plan growth or higher.


GET /dashboard/overview

Returns the main dashboard summary: total entries, total users, health score, and query counts.

Auth: JWT (manager+) · Plan: Growth+

Cache: Results are pre-warmed by the Celery task output.dashboard.warm_dashboard_cache and served from Redis under dashboard:overview:<org_id> with a 10-minute TTL. On a cache miss or Redis failure the endpoint falls back to live database queries transparently (logged at WARNING). The other endpoints always hit the database directly.

curl -s \
  -H "Authorization: Bearer $TOKEN" \
  https://api.knora.io/api/v1/dashboard/overview | jq .

Response 200 OK

{
  "total_entries": 412,
  "total_users": 28,
  "health_score": {
    "coverage": 83.33,
    "freshness": 61.40,
    "verification": 78.88,
    "gaps": 91.20,
    "overall": 78.32
  },
  "total_queries": 1045,
  "unanswered_queries": 92
}
Field Type Description
total_entries integer Total non-archived knowledge entries
total_users integer Total active user accounts
health_score object Knowledge health breakdown — see HealthScore schema
total_queries integer Cumulative queries submitted by all users
unanswered_queries integer Queries that received no matching entry answer

GET /dashboard/health

Returns the standalone HealthScore object for the organisation. Useful for polling health independently without fetching the full overview payload. Returns the same object embedded in /dashboard/overview.

Auth: JWT (manager+) · Plan: Growth+

curl -s \
  -H "Authorization: Bearer $TOKEN" \
  https://api.knora.io/api/v1/dashboard/health | jq .

Response 200 OK

{
  "coverage": 83.33,
  "freshness": 61.40,
  "verification": 78.88,
  "gaps": 91.20,
  "overall": 78.32
}

See HealthScore schema for field definitions.


GET /dashboard/activity

Returns a time-sorted feed of recent events: entry creations, verifications, queries, and flags. The feed covers the last 7 days regardless of limit. Events are fetched up to limit // 4 (minimum 5) per event type, then merged, sorted descending by timestamp, and capped at limit.

Auth: JWT (manager+) · Plan: Growth+

Query parameters

Parameter Type Default Max Description
limit integer 20 100 Maximum number of activity events to return
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  "https://api.knora.io/api/v1/dashboard/activity?limit=50" | jq .

Response 200 OK

{
  "activities": [
    {
      "type": "entry_created",
      "entry_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "entry_title": "Onboarding Checklist",
      "user_id": "a1b2c3d4-0000-0000-0000-000000000001",
      "user_name": "Alice Smith",
      "timestamp": "2026-05-31T14:22:00Z",
      "details": null
    },
    {
      "type": "query_made",
      "entry_id": null,
      "entry_title": null,
      "user_id": "a1b2c3d4-0000-0000-0000-000000000002",
      "user_name": "Bob Jones",
      "timestamp": "2026-05-31T13:55:10Z",
      "details": "How do I submit an expense report?"
    }
  ],
  "total": 2
}

activities[].type values

Value Meaning
entry_created A new knowledge entry was created
entry_verified An entry was marked as verified
query_made A user submitted a question; details contains the first 100 characters of the query text
entry_flagged An entry was flagged for review

Activity item fields

Field Type Nullable Description
type string No Event type (see table above)
entry_id UUID Yes Relevant entry ID (null for query_made)
entry_title string Yes Entry title (null for query_made)
user_id UUID Yes User who triggered the event
user_name string Yes Display name of the user
timestamp ISO 8601 datetime No When the event occurred
details string Yes Extra context; populated only for query_made

GET /dashboard/departments

Returns per-department statistics: entry counts, coverage percentage, bus-factor risk level, and verification status. Departments are sorted by entry_count descending. If bus-factor computation fails, risk_level defaults to "low" for all departments and a warning is logged.

Auth: JWT (manager+) · Plan: Growth+

curl -s \
  -H "Authorization: Bearer $TOKEN" \
  https://api.knora.io/api/v1/dashboard/departments | jq .

Response 200 OK

{
  "departments": [
    {
      "department_id": "d1000000-0000-0000-0000-000000000001",
      "department_name": "Engineering",
      "entry_count": 87,
      "coverage": 100.0,
      "risk_level": "low",
      "verified_count": 72,
      "needs_review_count": 5
    },
    {
      "department_id": "d2000000-0000-0000-0000-000000000002",
      "department_name": "Finance",
      "entry_count": 4,
      "coverage": 40.0,
      "risk_level": "critical",
      "verified_count": 1,
      "needs_review_count": 3
    }
  ],
  "total": 2
}

Department stat fields

Field Type Description
department_id UUID Unique identifier of the department
department_name string Human-readable department name
entry_count integer Total non-archived knowledge entries
coverage float 0–100 Entry coverage percentage. 100% when entry_count >= 10; scales linearly below that threshold
risk_level string Bus-factor concentration risk: critical / high / medium / low
verified_count integer Entries with verified status
needs_review_count integer Entries flagged as needing review

GET /dashboard/trending

Returns the most frequently asked questions in the organisation over a rolling look-back window. Always capped at the top 10 results.

Auth: JWT (manager+) · Plan: Growth+

Query parameters

Parameter Type Default Description
days integer 7 Look-back window in days
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  "https://api.knora.io/api/v1/dashboard/trending?days=30" | jq .

Response 200 OK

{
  "queries": [
    {
      "query_text": "How do I request parental leave?",
      "count": 34,
      "has_answer": true,
      "last_asked_at": "2026-05-31T16:45:00Z"
    },
    {
      "query_text": "How do I get access to the production environment?",
      "count": 18,
      "has_answer": false,
      "last_asked_at": "2026-05-31T11:20:00Z"
    }
  ],
  "days": 7,
  "total": 2
}

Trending query fields

Field Type Nullable Description
query_text string No The exact query string submitted
count integer No Number of times asked in the window
has_answer boolean No Whether at least one matching knowledge entry exists
last_asked_at ISO 8601 datetime Yes Timestamp of the most recent occurrence

Queries with has_answer: false represent knowledge gaps and can be used to prioritise new entry creation.


HealthScore

Returned inside OverviewResponse.health_score and as the standalone response from GET /dashboard/health.

All sub-scores are floats in the range 0.0 – 100.0 (two decimal places).

Field Weight Calculation
coverage 25% Percentage of departments that have at least 10 entries
freshness 25% Percentage of entries reviewed in the last 30 days
verification 30% Percentage of entries with verified status
gaps 20% answered_queries / total_queries * 100; defaults to 100 when no queries exist
overall Weighted average: coverage×0.25 + freshness×0.25 + verification×0.30 + gaps×0.20