Admin API¶
The Admin REST API provides HTTP endpoints for managing knowledge insights and changesets, and for listing every user's memory records, outside the MCP protocol. Use it for building dashboards, integrating with existing governance tools, or scripting batch operations.
Authentication¶
All endpoints require admin authentication via API key. Pass the key as either:
X-API-Key: <key>headerAuthorization: Bearer <key>header
The key must resolve to a user with the admin role. Requests without valid credentials receive 401 Unauthorized. Requests with a valid key but no admin role receive 403 Forbidden.
Insight Endpoints¶
List Insights¶
Returns a paginated list of insights with optional filtering.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status: pending, approved, rejected, applied, superseded |
category |
string | Filter by category: correction, business_context, data_quality, usage_guidance, relationship, enhancement |
entity_urn |
string | Filter by related entity URN |
captured_by |
string | Filter by the user who captured the insight |
confidence |
string | Filter by confidence level: high, medium, low |
source |
string | Filter by source: user, agent_discovery, enrichment_gap |
since |
RFC 3339 | Filter insights created after this timestamp |
until |
RFC 3339 | Filter insights created before this timestamp |
page |
integer | Page number, 1-based (default: 1) |
per_page |
integer | Results per page (default: 20, max: 100) |
Example:
curl -s "https://mcp.example.com/api/v1/admin/knowledge/insights?status=pending&category=correction" \
-H "Authorization: Bearer $ADMIN_API_KEY" | jq
Response:
{
"data": [
{
"id": "a1b2c3d4e5f67890a1b2c3d4e5f67890",
"created_at": "2025-01-15T14:30:00Z",
"session_id": "sess_abc123",
"captured_by": "[email protected]",
"persona": "analyst",
"source": "user",
"category": "correction",
"insight_text": "The amount column represents gross margin before returns, not revenue.",
"confidence": "high",
"entity_urns": [
"mcp:dataset:(trino,warehouse,hive.sales.orders)"
],
"related_columns": [],
"suggested_actions": [
{
"action_type": "update_description",
"target": "amount",
"detail": "Gross margin before returns"
}
],
"status": "pending"
}
],
"total": 1,
"page": 1,
"per_page": 20
}
Get Insight¶


The portal's review drawer shows the same insight; the fields below are what this endpoint returns for it.
Returns a single insight by ID.
Example:
curl -s "https://mcp.example.com/api/v1/admin/knowledge/insights/a1b2c3d4e5f67890a1b2c3d4e5f67890" \
-H "Authorization: Bearer $ADMIN_API_KEY" | jq
Response:
{
"id": "a1b2c3d4e5f67890a1b2c3d4e5f67890",
"created_at": "2026-01-15T14:30:00Z",
"session_id": "sess_abc123",
"captured_by": "[email protected]",
"persona": "analyst",
"source": "user",
"category": "correction",
"insight_text": "The amount column represents gross margin before returns, not revenue.",
"confidence": "high",
"entity_urns": [
"mcp:dataset:(trino,warehouse,hive.sales.orders)"
],
"related_columns": [
{
"urn": "mcp:dataset:(trino,warehouse,hive.sales.orders)",
"column": "amount",
"relevance": "direct"
}
],
"suggested_actions": [
{
"action_type": "update_description",
"target": "amount",
"detail": "Gross margin before returns"
}
],
"status": "pending",
"observed_entities": [
{
"urn": "mcp:dataset:(trino,warehouse,hive.sales.orders)",
"query_table": "hive.sales.orders",
"connection": "primary",
"estimated_rows": 1200
}
]
}
Observed Warehouse State¶
A pending insight is a claim awaiting certification, and some claims are about entities the platform can query itself. When a pending insight's entity URN resolves through the configured query provider to an available table, the list and detail payloads carry that observation beside the claim in observed_entities, one entry per resolved URN, in the order the insight carries them.
| Field | Type | Description |
|---|---|---|
urn |
string | The entity URN this observation is for |
query_table |
string | What the entity is queryable as, e.g. hive.sales.orders |
connection |
string | The query connection the table lives on |
estimated_rows |
integer | Rows the engine currently estimates. Present only when enrichment.estimate_row_counts is on (Configuration) |
conflict |
object | Advisory marker: claimed_rows, observed_rows, and a message naming both |
conflict is raised when the claim text states an integer and the table estimates a different one. It is advisory: an estimate is an estimate, the number in the claim may be about something else, and promotion is never refused mechanically — approve and reject behave exactly as they do without it. When a claim states several numbers, the one nearest the estimate is compared, since if even that number disagrees with the warehouse, every reading of the claim does.
observed_entities is omitted, not empty, whenever there is nothing observed:
- the insight is not
pending(a decided insight is history, not a decision to inform) - the URN does not resolve, or the provider reports the table unavailable
- the query provider is absent or
noop - the lookups did not finish inside the read path's budget
In every one of those cases the payload is byte-identical to what the endpoint served before it could observe anything, so a client that does not know the field is unaffected.
Update Insight¶
Update the text, category, or confidence of an insight. Only pending insights can be edited.
Request Body:
{
"insight_text": "Updated description of the insight",
"category": "business_context",
"confidence": "high"
}
All fields are optional. Only provided fields are updated.
Example:
curl -X PUT "https://mcp.example.com/api/v1/admin/knowledge/insights/a1b2c3d4e5f67890" \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"confidence": "high"}'
Response: Returns the updated insight (same structure as Get Insight).
Update Insight Status¶
Approve or reject an insight.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | Yes | Target status: approved or rejected |
review_notes |
string | No | Notes explaining the decision |
Valid Transitions:
| From | To |
|---|---|
pending |
approved |
pending |
rejected |
pending |
superseded |
Example:
curl -X PUT "https://mcp.example.com/api/v1/admin/knowledge/insights/a1b2c3d4e5f67890/status" \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "approved", "review_notes": "Confirmed by data team"}'
Response:
{
"id": "a1b2c3d4e5f67890a1b2c3d4e5f67890",
"status": "approved",
"reviewed_by": "[email protected]",
"reviewed_at": "2026-04-15T16:00:00Z",
"review_notes": "Confirmed by data team"
}
Get Insight Statistics¶
Returns aggregate statistics about insights.
Example:
curl -s "https://mcp.example.com/api/v1/admin/knowledge/insights/stats" \
-H "Authorization: Bearer $ADMIN_API_KEY" | jq
Response:
{
"total_pending": 7,
"by_entity": [
{
"entity_urn": "mcp:dataset:(trino,warehouse,hive.sales.orders)",
"count": 3,
"categories": ["correction", "business_context"],
"latest_at": "2025-01-15T14:30:00Z"
}
],
"by_category": {
"correction": 5,
"business_context": 3,
"data_quality": 2
},
"by_confidence": {
"high": 4,
"medium": 5,
"low": 1
},
"by_status": {
"pending": 7,
"approved": 3,
"applied": 12,
"rejected": 2
}
}
Changeset Endpoints¶
List Changesets¶
Returns a paginated list of changesets with optional filtering.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
entity_urn |
string | Filter by target entity URN |
applied_by |
string | Filter by the user who applied the changes |
rolled_back |
boolean | Filter by rollback status (true or false) |
since |
RFC 3339 | Filter changesets created after this timestamp |
until |
RFC 3339 | Filter changesets created before this timestamp |
page |
integer | Page number, 1-based (default: 1) |
per_page |
integer | Results per page (default: 20, max: 100) |
Example:
curl -s "https://mcp.example.com/api/v1/admin/knowledge/changesets?rolled_back=false" \
-H "Authorization: Bearer $ADMIN_API_KEY" | jq
Response:
{
"changesets": [
{
"id": "cs_x1y2z3a4b5c6d7e8f9a0b1c2d3e4f5a6",
"created_at": "2025-01-15T16:00:00Z",
"target_urn": "mcp:dataset:(trino,warehouse,hive.sales.orders)",
"change_type": "update_description",
"previous_value": {
"description": "Order records",
"tags": ["financial"],
"glossary_terms": [],
"owners": ["Data Platform Team"]
},
"new_value": {
"change_0": {
"change_type": "update_description",
"target": "entity",
"detail": "Order records with gross margin amounts (before returns)"
}
},
"source_insight_ids": ["a1b2c3d4e5f67890"],
"applied_by": "[email protected]",
"rolled_back": false
}
],
"total": 1,
"page": 1,
"per_page": 20
}
Get Changeset¶
Returns a single changeset by ID.
Example:
curl -s "https://mcp.example.com/api/v1/admin/knowledge/changesets/cs_x1y2z3a4b5c6" \
-H "Authorization: Bearer $ADMIN_API_KEY" | jq
Response: Same structure as a single item from the list response.
{
"id": "cs_x1y2z3a4b5c6d7e8f9a0b1c2d3e4f5a6",
"created_at": "2026-01-15T16:00:00Z",
"target_urn": "mcp:dataset:(trino,warehouse,hive.sales.orders)",
"change_type": "update_description",
"previous_value": {
"description": "Order records",
"tags": ["financial"],
"glossary_terms": [],
"owners": ["Data Platform Team"]
},
"new_value": {
"change_0": {
"change_type": "update_description",
"target": "entity",
"detail": "Order records with gross margin amounts (before returns)"
}
},
"source_insight_ids": ["a1b2c3d4e5f67890"],
"approved_by": "[email protected]",
"applied_by": "[email protected]",
"rolled_back": false
}
Rollback Changeset¶
Restores every catalog aspect the changeset wrote to the value it replaced, in one transaction, returns the changeset's source insights to the review queue as pending, and marks the changeset rolled back. Uses the same revert engine as the apply_knowledge MCP rollback action; see Governance: Rollback for the full semantics.
Example:
curl -X POST "https://mcp.example.com/api/v1/admin/knowledge/changesets/cs_x1y2z3a4b5c6/rollback" \
-H "Authorization: Bearer $ADMIN_API_KEY"
Response:
{
"changeset_id": "cs_x1y2z3a4b5c6",
"target_urn": "mcp:dataset:(trino,warehouse,hive.sales.orders)",
"reverted_changes": ["restored glossary_terms of mcp:dataset:(trino,warehouse,hive.sales.orders)"],
"skipped_changes": [],
"insights_returned_to_review": ["a1b2c3d4e5f6"],
"rolled_back_by": "[email protected]"
}
Status codes:
| Status | Condition |
|---|---|
200 |
Reverted and recorded. |
404 |
Changeset not found. |
409 |
Already rolled back; an aspect it wrote has been written again since; or it was written before the platform catalog held its entities, so its writes are not in the catalog's history. |
422 |
The changeset created a prompt, which a rollback does not delete. |
Memory Record Endpoints¶
List Memory Records¶
Returns every memory record on the deployment, whoever wrote it, newest first. The portal's GET /api/v1/portal/memory/records lists only the caller's own records; this route is how an administrator sees, counts and audits all of them. It takes the portal route's filters and its limit/offset paging, plus created_by to narrow to one author.
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
created_by |
string | Filter by the author's email |
dimension |
string | Filter by dimension |
sink_class |
string | Filter by sink class |
category |
string | Filter by category |
status |
string | Filter by status |
source |
string | Filter by source |
limit |
integer | Results per page (default: 20, max: 100) |
offset |
integer | Records to skip (default: 0) |
Example:
curl -s "https://mcp.example.com/api/v1/admin/memory/[email protected]&limit=50" \
-H "Authorization: Bearer $ADMIN_API_KEY" | jq
Response:
{
"data": [
{
"id": "mem_a1b2c3d4e5f6",
"created_at": "2026-03-18T08:11:08Z",
"updated_at": "2026-03-18T08:11:08Z",
"created_by": "[email protected]",
"persona": "analyst",
"dimension": "knowledge",
"content": "The daily_sales table in the retail schema is partitioned by date.",
"category": "business_context",
"confidence": "high",
"source": "user",
"entity_urns": [],
"related_columns": [],
"metadata": {},
"status": "active"
}
],
"total": 212,
"limit": 50,
"offset": 0
}
The route is registered only when the deployment has a memory store (a database). Like every route here it is behind the admin gate, so a caller without the admin persona is refused.
Error Responses¶
All endpoints return errors in a consistent format:
| HTTP Status | Code | Description |
|---|---|---|
400 |
BAD_REQUEST |
Invalid request parameters or body |
401 |
UNAUTHORIZED |
Missing or invalid authentication |
403 |
FORBIDDEN |
Authenticated but not authorized (not admin) |
404 |
NOT_FOUND |
Resource not found |
409 |
CONFLICT |
Invalid status transition or already rolled back |
500 |
INTERNAL_ERROR |
Server error |
Database Schema¶
Knowledge capture uses two PostgreSQL tables, created by migrations 000006, 000007, and 000008.
knowledge_insights¶
| Column | Type | Description |
|---|---|---|
id |
TEXT | Primary key (cryptographic random hex) |
created_at |
TIMESTAMPTZ | When the insight was captured |
session_id |
TEXT | MCP session that produced the insight |
captured_by |
TEXT | User who shared the knowledge |
persona |
TEXT | Active persona at capture time |
source |
TEXT | Where the knowledge came from: user, agent_discovery, enrichment_gap |
category |
TEXT | Insight category |
insight_text |
TEXT | The domain knowledge content |
confidence |
TEXT | Confidence level (high, medium, low) |
entity_urns |
JSONB | Related catalog references |
related_columns |
JSONB | Related columns |
suggested_actions |
JSONB | Proposed catalog changes |
status |
TEXT | Current lifecycle status |
reviewed_by |
TEXT | Who reviewed the insight |
reviewed_at |
TIMESTAMPTZ | When it was reviewed |
review_notes |
TEXT | Reviewer comments |
applied_by |
TEXT | Who applied the insight |
applied_at |
TIMESTAMPTZ | When it was applied |
changeset_ref |
TEXT | Link to the changeset |
knowledge_changesets¶
| Column | Type | Description |
|---|---|---|
id |
TEXT | Primary key (cryptographic random hex) |
created_at |
TIMESTAMPTZ | When changes were applied |
target_urn |
TEXT | Catalog entity that was modified |
change_type |
TEXT | Type of changes applied |
previous_value |
JSONB | Metadata before changes (for rollback) |
new_value |
JSONB | Changes applied |
source_insight_ids |
JSONB | Insights that produced this changeset |
approved_by |
TEXT | Who approved the changes |
applied_by |
TEXT | Who applied the changes |
rolled_back |
BOOLEAN | Whether changes were reverted |
rolled_back_by |
TEXT | Who reverted the changes |
rolled_back_at |
TIMESTAMPTZ | When changes were reverted |