Admin API¶
The Admin REST API provides HTTP endpoints for managing knowledge insights and changesets 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": [
"urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)"
],
"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": [
"urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)"
],
"related_columns": [
{
"urn": "urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)",
"column": "amount",
"relevance": "direct"
}
],
"suggested_actions": [
{
"action_type": "update_description",
"target": "amount",
"detail": "Gross margin before returns"
}
],
"status": "pending",
"observed_entities": [
{
"urn": "urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)",
"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": "urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)",
"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": "urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)",
"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": "urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)",
"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¶
Reverts the DataHub aspects the changeset mutated back to their before-image, 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": "urn:li:dataset:(urn:li:dataPlatform:trino,hive.sales.orders,PROD)",
"reverted_changes": ["removed glossary term urn:li:glossaryTerm:gross-margin"],
"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, or a newer changeset has since modified the same aspect. |
422 |
Changeset contains change types whose prior state was not captured (column descriptions, structured properties, incidents, curated queries, context documents, prompts). |
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 DataHub entity URNs |
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 | DataHub 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 |