Skip to content
mcp-data-platform composable mcp data platform
v1.x part of txn2 ↗

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> header
  • Authorization: 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

GET /api/v1/admin/knowledge/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

An insight's detail drawer in the portalAn insight's detail drawer in the portal

The portal's review drawer shows the same insight; the fields below are what this endpoint returns for it.

GET /api/v1/admin/knowledge/insights/{id}

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

PUT /api/v1/admin/knowledge/insights/{id}

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

PUT /api/v1/admin/knowledge/insights/{id}/status

Approve or reject an insight.

Request Body:

{
  "status": "approved",
  "review_notes": "Verified with data engineering team"
}
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

GET /api/v1/admin/knowledge/insights/stats

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

GET /api/v1/admin/knowledge/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

GET /api/v1/admin/knowledge/changesets/{id}

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

POST /api/v1/admin/knowledge/changesets/{id}/rollback

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:

{
  "error": "insight not found",
  "code": "NOT_FOUND"
}
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