Skip to content

Membrain API Reference

Complete reference for every HTTP endpoint exposed by the Membrain AI Safety Gateway.

Base URL: http://localhost:8000 (default)


Table of Contents

  1. Authentication
  2. Rate Limit Headers
  3. Error Response Format
  4. Health
  5. Chat Completions
  6. Anthropic Proxy
  7. Knowledge
  8. Audit
  9. Admin
  10. Reports
  11. Shadow AI
  12. Dashboard
  13. Metrics

Authentication

Membrain uses API keys for authentication. When a database is configured, API keys are validated against the api_keys table. When no database is configured, authentication is disabled and all requests are allowed.

API Key Format

Keys follow the format ck_live_<32 hex characters>, for example:

ck_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4

Providing the Key

Membrain accepts API keys via two headers (checked in this order):

Header Format Example
X-Membrain-API-Key Raw key X-Membrain-API-Key: ck_live_a1b2...
Authorization Bearer token Authorization: Bearer ck_live_a1b2...

Authentication Levels

Level Description
None No authentication required. Endpoint is publicly accessible.
Optional API key is accepted but not required. Invalid keys are rejected with 401.
Required (Admin) Valid API key is mandatory. Returns 401 if missing, 403 if inactive/expired.

Rate Limit Headers

When rate limiting is active, successful responses from /v1/chat/completions include these headers:

Header Type Description
X-RateLimit-Limit integer Maximum requests allowed in the current window
X-RateLimit-Remaining integer Requests remaining in the current window
X-RateLimit-Reset integer Unix timestamp when the rate limit window resets

Error Response Format

Standard Error (Chat/Dashboard/Admin endpoints)

{
  "detail": "Human-readable error message"
}

Common HTTP status codes:

Code Meaning
400 Bad request (invalid input, malformed UUID, etc.)
401 Authentication required or invalid API key
402 Budget exceeded
403 API key inactive or expired
404 Resource not found
409 Conflict (duplicate resource)
429 Rate limit exceeded (includes Retry-After header)
502 All upstream providers failed
503 Service unavailable (database or knowledge system not configured)
504 Upstream request timed out

Anthropic-Style Error (Anthropic proxy endpoints)

{
  "type": "error",
  "error": {
    "type": "authentication_error",
    "message": "Missing API key"
  }
}

Error types: authentication_error, invalid_request_error, api_error, timeout_error.


1. Health

GET /health

Simple health check to verify the service is running.

Authentication: None

Response Body:

Field Type Description
status string Always "ok"

Example:

curl http://localhost:8000/health
{
  "status": "ok"
}

2. Chat Completions

POST /v1/chat/completions

OpenAI-compatible chat completions endpoint. Runs the full middleware pipeline (PII sanitization, rate limiting, budget enforcement, caching, knowledge injection), routes to the appropriate provider with fallback, and logs an audit entry.

Authentication: None (pipeline may enforce per-key limits when X-Membrain-API-Key is provided)

Request Headers (optional routing controls):

Header Type Default Description
X-Membrain-Tier string "balanced" Routing tier: "fast", "balanced", "quality"
X-Membrain-Private string "" Set to "true" or "1" to restrict to private/local models
X-Membrain-Max-Cost string null Maximum cost per 1K tokens (as a float string)
X-Membrain-User-Id string null User identifier for audit and rate limiting
X-Membrain-Project string null Project identifier for audit and rate limiting

Request Body:

Field Type Required Default Description
model string Yes Model name (e.g., "gpt-4", "claude-sonnet-4-20250514")
messages array Yes List of chat messages
messages[].role string Yes Message role: "system", "user", "assistant"
messages[].content string No null Message content text
temperature float No null Sampling temperature (0.0 to 2.0)
max_tokens integer No null Maximum tokens to generate
stream boolean No false Enable SSE streaming

Response Body (non-streaming):

Field Type Description
id string Unique completion ID
object string Always "chat.completion"
created integer Unix timestamp of creation
model string Model that generated the response
choices array List of completion choices
choices[].index integer Choice index
choices[].message.role string Always "assistant"
choices[].message.content string Generated text
choices[].finish_reason string Stop reason: "stop", "length", etc.
usage.prompt_tokens integer Input tokens consumed
usage.completion_tokens integer Output tokens generated
usage.total_tokens integer Total tokens used

Response (streaming): Server-Sent Events (text/event-stream) with OpenAI-compatible data: {...} chunks.

Example:

curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "X-Membrain-Tier: quality" \
  -d '{
    "model": "gpt-4",
    "messages": [
      {"role": "user", "content": "Hello, world!"}
    ],
    "temperature": 0.7,
    "max_tokens": 100
  }'
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1709856000,
  "model": "gpt-4",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello! How can I help you today?"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 9,
    "total_tokens": 21
  }
}

Error Responses:

Code Condition
402 Budget exceeded
429 Rate limit exceeded (includes Retry-After header)
502 All providers failed

3. Anthropic Proxy

POST /v1/messages

Proxies requests to the upstream Anthropic Messages API. Sanitizes PII in user messages and system prompts before forwarding, then restores PII placeholders in the response. Supports both streaming and non-streaming modes. Preserves byte-exact representations of signed thinking blocks.

Authentication: Anthropic API key via X-API-Key header, Authorization header, or server-configured ANTHROPIC_API_KEY.

Forwarded Headers:

Header Description
x-api-key Anthropic API key
authorization Bearer token authentication
anthropic-version API version string
anthropic-beta Beta feature flags
content-type Request content type

Request Body: Standard Anthropic Messages API request body. Key fields:

Field Type Required Description
model string Yes Model name (e.g., "claude-sonnet-4-20250514")
messages array Yes Conversation messages
max_tokens integer Yes Maximum tokens to generate
stream boolean No Enable SSE streaming
system string No System prompt
temperature float No Sampling temperature

Response Body: Standard Anthropic Messages API response, passed through with PII restored.

Response Headers (forwarded from upstream):

Header Description
request-id Anthropic request ID
x-ratelimit-* Upstream Anthropic rate limit headers

Response (streaming): Server-Sent Events (text/event-stream) proxied from the Anthropic API with PII restored.

Example:

curl -X POST http://localhost:8000/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk-ant-..." \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "max_tokens": 256,
    "messages": [
      {"role": "user", "content": "What is the capital of France?"}
    ]
  }'
{
  "id": "msg_01abc...",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "The capital of France is Paris."
    }
  ],
  "model": "claude-sonnet-4-20250514",
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 15,
    "output_tokens": 10
  }
}

Error Responses:

Code Condition
400 Invalid JSON in request body
401 Missing API key
502 Failed to connect to upstream Anthropic API
504 Upstream request timed out

POST /v1/messages/count_tokens

Transparent passthrough to the Anthropic token counting endpoint. No PII sanitization is applied.

Authentication: Same as /v1/messages (Anthropic API key).

Request Body: Standard Anthropic token counting request body.

Response Body: Upstream response passed through verbatim.

Response Headers (forwarded from upstream):

Header Description
request-id Anthropic request ID
x-ratelimit-* Upstream Anthropic rate limit headers

Example:

curl -X POST http://localhost:8000/v1/messages/count_tokens \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk-ant-..." \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-4-20250514",
    "messages": [
      {"role": "user", "content": "Hello, world!"}
    ]
  }'
{
  "input_tokens": 12
}

Error Responses:

Code Condition
401 Missing API key
502 Failed to connect to upstream
504 Upstream request timed out

4. Knowledge

All knowledge endpoints are prefixed with /v1/knowledge.

POST /v1/knowledge

Add a single document or snippet to the knowledge store.

Authentication: None

Request Body:

Field Type Required Default Description
content string Yes Document text (1 to 100,000 characters)
user_id string No null User who contributed this knowledge
project string No null Project this knowledge belongs to

Response Body (201 Created):

Field Type Description
id string UUID of the created entry
content string Stored content
user_id string or null User identifier
project string or null Project identifier
source string or null Source tag (e.g., "api_manual")
trust_level float or null Trust score of the entry
created_at string ISO 8601 timestamp

Example:

curl -X POST http://localhost:8000/v1/knowledge \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Membrain supports PII detection for 25+ patterns including emails, SSNs, and credit cards.",
    "project": "docs"
  }'
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "content": "Membrain supports PII detection for 25+ patterns including emails, SSNs, and credit cards.",
  "user_id": null,
  "project": "docs",
  "source": "api_manual",
  "trust_level": null,
  "created_at": "2026-03-08T12:00:00+00:00"
}

GET /v1/knowledge/search

Semantic search over the knowledge store using vector similarity (pgvector).

Authentication: None

Query Parameters:

Parameter Type Required Default Description
q string Yes Search query (min 1 character)
limit integer No 5 Max results to return (1-50)
project string No null Filter by project
topic string No null Filter by topic

Response Body:

Field Type Description
query string The original search query
results array List of matching knowledge entries
results[].id string Entry UUID
results[].content string Entry content
results[].user_id string or null User identifier
results[].project string or null Project identifier
results[].source string or null Source tag
results[].trust_level float or null Trust score
results[].is_stale boolean Whether the entry is marked stale
results[].created_at string ISO 8601 timestamp

Example:

curl "http://localhost:8000/v1/knowledge/search?q=PII+detection&limit=3"
{
  "query": "PII detection",
  "results": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "content": "Membrain supports PII detection for 25+ patterns...",
      "user_id": null,
      "project": "docs",
      "source": "api_manual",
      "trust_level": 0.95,
      "is_stale": false,
      "created_at": "2026-03-08T12:00:00+00:00"
    }
  ]
}

DELETE /v1/knowledge/{entry_id}

Remove a knowledge entry by its UUID.

Authentication: None

Path Parameters:

Parameter Type Description
entry_id string (UUID) The UUID of the knowledge entry to delete

Response: 204 No Content on success.

Example:

curl -X DELETE http://localhost:8000/v1/knowledge/a1b2c3d4-e5f6-7890-abcd-ef1234567890

Error Responses:

Code Condition
400 Invalid UUID format
404 Knowledge entry not found
503 Knowledge system not available

POST /v1/knowledge/ingest

Bulk ingest multiple documents into the knowledge store.

Authentication: None

Request Body:

Field Type Required Description
documents array Yes List of documents to ingest
documents[].content string Yes Document text (1 to 100,000 chars)
documents[].user_id string No User identifier
documents[].project string No Project identifier

Response Body:

Field Type Description
ingested integer Number of documents successfully ingested
failed integer Number of documents that failed to ingest
ids array of strings UUIDs of successfully ingested entries

Example:

curl -X POST http://localhost:8000/v1/knowledge/ingest \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      {"content": "First document content", "project": "docs"},
      {"content": "Second document content", "project": "docs"}
    ]
  }'
{
  "ingested": 2,
  "failed": 0,
  "ids": [
    "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "b2c3d4e5-f6a1-8901-bcde-f12345678901"
  ]
}

GET /v1/knowledge/topics

Return all distinct topics across knowledge entries.

Authentication: None

Response Body:

Field Type Description
topics array of strings Sorted list of all unique topics

Example:

curl http://localhost:8000/v1/knowledge/topics
{
  "topics": ["architecture", "deployment", "pii-detection", "security"]
}

POST /v1/knowledge/consolidate

Trigger a knowledge consolidation job that marks stale entries, deduplicates by content hash, clusters similar entries, and cleans up unused stale entries.

Authentication: Required (Admin)

Request Body: None

Response Body:

Field Type Description
stale_marked integer Entries marked as stale
duplicates_merged integer Duplicate entries merged
clusters_summarized integer Similar entry clusters summarized
entries_cleaned integer Stale entries removed
duration_seconds float Job execution time
timestamp string ISO 8601 timestamp of the job run

Example:

curl -X POST http://localhost:8000/v1/knowledge/consolidate \
  -H "X-Membrain-API-Key: ck_live_a1b2c3d4..."
{
  "stale_marked": 5,
  "duplicates_merged": 3,
  "clusters_summarized": 1,
  "entries_cleaned": 2,
  "duration_seconds": 4.32,
  "timestamp": "2026-03-08T12:00:00+00:00"
}

Error Responses:

Code Condition
401 API key required
403 API key inactive
503 Knowledge system not available

5. Audit

Audit log data is exposed through the dashboard API. See Dashboard - Audit below.


6. Admin

All admin endpoints are prefixed with /api/admin and require a valid API key.

POST /api/admin/projects

Create a new project.

Authentication: Required (Admin)

Request Body:

Field Type Required Default Description
name string Yes Unique project slug (1-255 chars)
display_name string Yes Human-readable project name (1-255 chars)
default_rate_limit_rpm integer No 60 Default requests per minute for keys in this project
default_budget_daily_usd float No 0.0 Default daily budget in USD (0 = unlimited)
default_budget_monthly_usd float No 0.0 Default monthly budget in USD (0 = unlimited)
allowed_models array of strings No null Restrict keys to these models (null = all allowed)

Response Body (201 Created):

Field Type Description
id string UUID of the created project
name string Project slug
display_name string Human-readable name
is_active boolean Whether the project is active
default_rate_limit_rpm integer Default RPM limit
default_budget_daily_usd float Default daily budget
default_budget_monthly_usd float Default monthly budget
allowed_models array or null Allowed models list
created_at string ISO 8601 timestamp

Example:

curl -X POST http://localhost:8000/api/admin/projects \
  -H "Content-Type: application/json" \
  -H "X-Membrain-API-Key: ck_live_a1b2c3d4..." \
  -d '{
    "name": "engineering",
    "display_name": "Engineering Team",
    "default_rate_limit_rpm": 120,
    "default_budget_daily_usd": 50.0,
    "allowed_models": ["gpt-4", "claude-sonnet-4-20250514"]
  }'
{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "name": "engineering",
  "display_name": "Engineering Team",
  "is_active": true,
  "default_rate_limit_rpm": 120,
  "default_budget_daily_usd": 50.0,
  "default_budget_monthly_usd": 0.0,
  "allowed_models": ["gpt-4", "claude-sonnet-4-20250514"],
  "created_at": "2026-03-08T12:00:00+00:00"
}

Error Responses:

Code Condition
401 API key required or invalid
409 Project with that name already exists
503 Database not configured

GET /api/admin/projects

List all projects.

Authentication: Required (Admin)

Response Body: Array of project objects (same schema as POST response).

Example:

curl http://localhost:8000/api/admin/projects \
  -H "X-Membrain-API-Key: ck_live_a1b2c3d4..."
[
  {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "name": "engineering",
    "display_name": "Engineering Team",
    "is_active": true,
    "default_rate_limit_rpm": 120,
    "default_budget_daily_usd": 50.0,
    "default_budget_monthly_usd": 0.0,
    "allowed_models": ["gpt-4", "claude-sonnet-4-20250514"],
    "created_at": "2026-03-08T12:00:00+00:00"
  }
]

POST /api/admin/keys

Create a new API key. The raw key is returned once and never stored or shown again.

Authentication: Required (Admin)

Request Body:

Field Type Required Default Description
name string Yes Human-readable key name (1-255 chars)
project string Yes Project slug the key belongs to (1-255 chars)
user_id string No null User this key is associated with
rate_limit_rpm integer No null Per-key rate limit override (null = use project default)
budget_daily_usd float No null Per-key daily budget override
budget_monthly_usd float No null Per-key monthly budget override
allowed_models array of strings No null Per-key model restrictions
expires_at string (datetime) No null ISO 8601 expiration timestamp

Response Body (201 Created):

Field Type Description
id string UUID of the created API key
raw_key string The raw API key (shown only once)
name string Human-readable key name
project string Project slug
created_at string ISO 8601 timestamp

Example:

curl -X POST http://localhost:8000/api/admin/keys \
  -H "Content-Type: application/json" \
  -H "X-Membrain-API-Key: ck_live_a1b2c3d4..." \
  -d '{
    "name": "alice-dev-key",
    "project": "engineering",
    "user_id": "alice",
    "rate_limit_rpm": 30,
    "budget_daily_usd": 10.0
  }'
{
  "id": "e7c8d9a0-b1c2-4d3e-8f5a-6b7c8d9e0f1a",
  "raw_key": "ck_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  "name": "alice-dev-key",
  "project": "engineering",
  "created_at": "2026-03-08T12:00:00+00:00"
}

Error Responses:

Code Condition
401 API key required or invalid
404 Project not found
503 Database not configured

GET /api/admin/keys

List all API keys (raw key values are never included).

Authentication: Required (Admin)

Response Body: Array of key summary objects:

Field Type Description
id string UUID of the API key
name string Human-readable key name
project string Project slug
user_id string or null Associated user
is_active boolean Whether the key is active
rate_limit_rpm integer or null Per-key RPM limit
budget_daily_usd float or null Per-key daily budget
budget_monthly_usd float or null Per-key monthly budget
allowed_models array or null Per-key model restrictions
created_at string ISO 8601 creation timestamp
expires_at string or null ISO 8601 expiration timestamp

Example:

curl http://localhost:8000/api/admin/keys \
  -H "X-Membrain-API-Key: ck_live_a1b2c3d4..."
[
  {
    "id": "e7c8d9a0-b1c2-4d3e-8f5a-6b7c8d9e0f1a",
    "name": "alice-dev-key",
    "project": "engineering",
    "user_id": "alice",
    "is_active": true,
    "rate_limit_rpm": 30,
    "budget_daily_usd": 10.0,
    "budget_monthly_usd": null,
    "allowed_models": null,
    "created_at": "2026-03-08T12:00:00+00:00",
    "expires_at": null
  }
]

DELETE /api/admin/keys/{key_id}

Deactivate an API key (soft delete). The key is marked inactive but not removed from the database.

Authentication: Required (Admin)

Path Parameters:

Parameter Type Description
key_id string (UUID) The UUID of the API key to deactivate

Response Body (200 OK):

Field Type Description
detail string Confirmation message

Example:

curl -X DELETE http://localhost:8000/api/admin/keys/e7c8d9a0-b1c2-4d3e-8f5a-6b7c8d9e0f1a \
  -H "X-Membrain-API-Key: ck_live_a1b2c3d4..."
{
  "detail": "API key 'alice-dev-key' deactivated."
}

Error Responses:

Code Condition
400 Invalid key ID format
401 API key required or invalid
404 API key not found
503 Database not configured

7. Reports

All report endpoints are prefixed with /api/dashboard/reports.

GET /api/dashboard/reports/pii-summary

PII detection summary with category breakdown, daily trend, and top models.

Authentication: Optional

Query Parameters:

Parameter Type Required Default Description
days integer No 30 Look-back window in days (1-365)
project string No null Filter by project

Response Body:

Field Type Description
total_detections integer Total PII detections in the window
categories array PII category breakdown
categories[].category string PII category name (e.g., "EMAIL", "SSN")
categories[].count integer Number of detections
categories[].percentage float Percentage of total detections
daily_trend array Daily detection counts
daily_trend[].date string Date in YYYY-MM-DD format
daily_trend[].count integer Detections on that day
top_models array Models with most PII detections
top_models[].model string Model name
top_models[].pii_count integer Detection count

Example:

curl "http://localhost:8000/api/dashboard/reports/pii-summary?days=7"
{
  "total_detections": 42,
  "categories": [
    {"category": "EMAIL", "count": 20, "percentage": 47.6},
    {"category": "PHONE", "count": 12, "percentage": 28.6},
    {"category": "SSN", "count": 10, "percentage": 23.8}
  ],
  "daily_trend": [
    {"date": "2026-03-02", "count": 5},
    {"date": "2026-03-03", "count": 8},
    {"date": "2026-03-04", "count": 6},
    {"date": "2026-03-05", "count": 7},
    {"date": "2026-03-06", "count": 9},
    {"date": "2026-03-07", "count": 4},
    {"date": "2026-03-08", "count": 3}
  ],
  "top_models": [
    {"model": "gpt-4", "pii_count": 25},
    {"model": "claude-sonnet-4-20250514", "pii_count": 17}
  ]
}

GET /api/dashboard/reports/compliance

Full compliance report combining PII detections, request volume, cost, and model usage.

Authentication: Optional

Query Parameters:

Parameter Type Required Default Description
days integer No 30 Look-back window in days (1-365)
project string No null Filter by project

Response Body:

Field Type Description
generated_at string ISO 8601 generation timestamp
date_range_start string ISO 8601 start of the window
date_range_end string ISO 8601 end of the window
total_requests integer Total requests in the window
unique_users integer Count of distinct users
pii_detection_rate float Percentage of requests containing PII
total_pii_detections integer Total PII detections
pii_categories array PII category breakdown (same as PII summary)
model_usage array Per-model usage data
model_usage[].model string Model name
model_usage[].requests integer Request count
model_usage[].cost_usd float Total cost in USD
total_cost_usd float Total cost across all models
daily_request_counts array Daily request volume
daily_request_counts[].date string Date in YYYY-MM-DD format
daily_request_counts[].count integer Request count

Example:

curl "http://localhost:8000/api/dashboard/reports/compliance?days=30&project=engineering"
{
  "generated_at": "2026-03-08T12:00:00+00:00",
  "date_range_start": "2026-02-06T12:00:00+00:00",
  "date_range_end": "2026-03-08T12:00:00+00:00",
  "total_requests": 1250,
  "unique_users": 15,
  "pii_detection_rate": 12.5,
  "total_pii_detections": 156,
  "pii_categories": [
    {"category": "EMAIL", "count": 80, "percentage": 51.3}
  ],
  "model_usage": [
    {"model": "gpt-4", "requests": 800, "cost_usd": 24.5},
    {"model": "claude-sonnet-4-20250514", "requests": 450, "cost_usd": 13.2}
  ],
  "total_cost_usd": 37.7,
  "daily_request_counts": [
    {"date": "2026-02-06", "count": 40},
    {"date": "2026-02-07", "count": 45}
  ]
}

GET /api/dashboard/reports/export

Export a report as JSON or CSV.

Authentication: Optional

Query Parameters:

Parameter Type Required Default Description
format string No "json" Export format: "json" or "csv"
report string No "compliance" Report type: "compliance" or "pii-summary"
days integer No 30 Look-back window in days (1-365)
project string No null Filter by project

Response: - JSON format: Returns the report object directly (same schema as the corresponding report endpoint). - CSV format: Returns a text/csv file download with Content-Disposition: attachment; filename="{report}-report.csv".

Example (JSON):

curl "http://localhost:8000/api/dashboard/reports/export?format=json&report=pii-summary&days=7"

Example (CSV):

curl -o compliance-report.csv \
  "http://localhost:8000/api/dashboard/reports/export?format=csv&report=compliance&days=30"

8. Shadow AI

Shadow AI detection endpoints are prefixed with /api/dashboard.

GET /api/dashboard/shadow

Full report of all detected AI tool usage across the organization. Tracks User-Agent strings, source IPs, and request patterns to identify both approved and unapproved AI tools.

Authentication: Optional

Query Parameters:

Parameter Type Required Default Description
provider string No null Filter by provider name
approved_only boolean No false Show only approved tools
unapproved_only boolean No false Show only unapproved tools
limit integer No 100 Max results to return (1-500)

Response Body:

Field Type Description
tools array List of detected tools (sorted by request count, descending)
tools[].tool_name string Classified tool name (e.g., "Cursor", "GitHub Copilot", "Claude CLI")
tools[].user_agent string Raw User-Agent string
tools[].provider string AI provider being called
tools[].model string Most recent model used
tools[].source_ip string Source IP address
tools[].request_count integer Total requests from this tool
tools[].first_seen string ISO 8601 timestamp of first detection
tools[].last_seen string ISO 8601 timestamp of most recent detection
tools[].is_approved boolean Whether the tool is in the approved list
total_tools integer Total number of unique tools detected
total_requests integer Total request count across all tools
unapproved_count integer Number of unapproved tools

Recognized Tool Classifications:

User-Agent pattern Tool Name
cursor Cursor
copilot or github GitHub Copilot
claude-cli or claude-code Claude CLI
openai-python OpenAI Python SDK
anthropic-python Anthropic Python SDK
chatgpt ChatGPT
mozilla, chrome, safari Browser
python-httpx or python-requests Python HTTP Client
node-fetch or axios Node.js HTTP Client
(other) Unknown

Example:

curl "http://localhost:8000/api/dashboard/shadow?unapproved_only=true"
{
  "tools": [
    {
      "tool_name": "Cursor",
      "user_agent": "Cursor/0.45.1",
      "provider": "openai",
      "model": "gpt-4",
      "source_ip": "10.0.1.42",
      "request_count": 237,
      "first_seen": "2026-03-01T08:15:00+00:00",
      "last_seen": "2026-03-08T11:30:00+00:00",
      "is_approved": false
    }
  ],
  "total_tools": 1,
  "total_requests": 237,
  "unapproved_count": 1
}

GET /api/dashboard/shadow/overview

High-level shadow AI overview for the dashboard, including per-provider breakdown.

Authentication: Optional

Response Body:

Field Type Description
total_unique_tools integer Number of distinct tool types detected
total_requests integer Total requests across all shadow tools
unapproved_tools integer Number of unapproved tool types
providers array Per-provider statistics
providers[].provider string Provider name
providers[].tool_count integer Number of tool instances for this provider
providers[].request_count integer Total requests to this provider

Example:

curl http://localhost:8000/api/dashboard/shadow/overview
{
  "total_unique_tools": 4,
  "total_requests": 1520,
  "unapproved_tools": 2,
  "providers": [
    {"provider": "anthropic", "tool_count": 3, "request_count": 890},
    {"provider": "openai", "tool_count": 5, "request_count": 630}
  ]
}

9. Dashboard

All dashboard endpoints are prefixed with /api/dashboard.

GET /api/dashboard/overview

Aggregate overview statistics for the dashboard.

Authentication: Optional

Response Body:

Field Type Description
total_requests integer Total requests processed
total_cost_usd float Estimated total cost in USD
cache_hit_rate float Cache hit rate (0.0 to 1.0)
active_users integer Number of active users (currently 0; reserved)
pii_detections integer Total PII detections across all requests

Example:

curl http://localhost:8000/api/dashboard/overview
{
  "total_requests": 1250,
  "total_cost_usd": 37.65,
  "cache_hit_rate": 0.0,
  "active_users": 0,
  "pii_detections": 156
}

GET /api/dashboard/costs

Cost breakdown by provider and model.

Authentication: Optional

Response Body:

Field Type Description
breakdown array Per-provider/model cost data
breakdown[].provider string Provider name
breakdown[].model string Model name
breakdown[].total_cost_usd float Total cost for this model
breakdown[].total_tokens integer Total tokens consumed
breakdown[].request_count integer Number of requests

Example:

curl http://localhost:8000/api/dashboard/costs
{
  "breakdown": [
    {
      "provider": "openai",
      "model": "gpt-4",
      "total_cost_usd": 24.50,
      "total_tokens": 125000,
      "request_count": 800
    },
    {
      "provider": "anthropic",
      "model": "claude-sonnet-4-20250514",
      "total_cost_usd": 13.15,
      "total_tokens": 98000,
      "request_count": 450
    }
  ]
}

GET /api/dashboard/audit

Paginated audit log entries with optional filters.

Authentication: Optional

Query Parameters:

Parameter Type Required Default Description
page integer No 1 Page number (1-based)
page_size integer No 50 Entries per page (1-100)
user_id string No null Filter by user ID (reserved)
project string No null Filter by project (reserved)
provider string No null Filter by provider name

Response Body:

Field Type Description
entries array Audit log entries for the current page
entries[].id string Unique entry ID
entries[].created_at string ISO 8601 timestamp
entries[].user_id string or null User identifier
entries[].project string or null Project identifier
entries[].provider string Provider name
entries[].model string Model name
entries[].prompt_tokens integer Input tokens
entries[].completion_tokens integer Output tokens
entries[].cost_usd float Estimated cost in USD
entries[].duration_ms integer Request duration in milliseconds
entries[].streaming boolean Whether the request was streaming
entries[].pii_findings_count integer Number of PII items detected
entries[].pii_labels array of strings PII category labels (e.g., ["EMAIL_1", "SSN_1"])
entries[].pii_mapping object Map of PII placeholders to original values
total integer Total number of entries (across all pages)
page integer Current page number
page_size integer Page size

Example:

curl "http://localhost:8000/api/dashboard/audit?page=1&page_size=10&provider=openai"
{
  "entries": [
    {
      "id": "a1b2c3d4e5f6",
      "created_at": "2026-03-08T12:00:00+00:00",
      "user_id": "alice",
      "project": "engineering",
      "provider": "openai",
      "model": "gpt-4",
      "prompt_tokens": 150,
      "completion_tokens": 80,
      "cost_usd": 0.0069,
      "duration_ms": 1230,
      "streaming": false,
      "pii_findings_count": 2,
      "pii_labels": ["EMAIL_1", "PHONE_1"],
      "pii_mapping": {
        "[EMAIL_1]": "alice@example.com",
        "[PHONE_1]": "555-0123"
      }
    }
  ],
  "total": 1,
  "page": 1,
  "page_size": 10
}

GET /api/dashboard/pii

All PII values detected across requests, with category filtering.

Authentication: Optional

Query Parameters:

Parameter Type Required Default Description
category string No null Filter by PII category (e.g., "EMAIL", "SSN")
limit integer No 100 Max findings to return (1-500)

Response Body:

Field Type Description
findings array PII detection records
findings[].placeholder string PII placeholder used (e.g., "[EMAIL_1]")
findings[].value string Original PII value
findings[].category string PII category (e.g., "EMAIL")
findings[].request_id string Audit entry ID where PII was found
findings[].model string Model used in the request
findings[].detected_at string ISO 8601 detection timestamp
total integer Total findings returned

Example:

curl "http://localhost:8000/api/dashboard/pii?category=EMAIL&limit=5"
{
  "findings": [
    {
      "placeholder": "[EMAIL_1]",
      "value": "alice@example.com",
      "category": "EMAIL",
      "request_id": "a1b2c3d4e5f6",
      "model": "gpt-4",
      "detected_at": "2026-03-08T12:00:00+00:00"
    }
  ],
  "total": 1
}

POST /api/dashboard/knowledge/search

Search knowledge entries from the dashboard. Uses semantic search via pgvector when available, falls back to in-memory text search.

Authentication: Optional

Request Body:

Field Type Required Default Description
query string Yes Search query text
project string No null Filter by project
limit integer No 10 Maximum results

Response Body:

Field Type Description
results array Matching knowledge entries
results[].id string Entry ID
results[].content string Entry content
results[].user_id string or null User identifier
results[].project string or null Project identifier
results[].created_at string ISO 8601 timestamp

Example:

curl -X POST http://localhost:8000/api/dashboard/knowledge/search \
  -H "Content-Type: application/json" \
  -d '{"query": "PII detection", "limit": 5}'
{
  "results": [
    {
      "id": "a1b2c3d4e5f6",
      "content": "Membrain supports PII detection for 25+ patterns...",
      "user_id": null,
      "project": "docs",
      "created_at": "2026-03-08T12:00:00+00:00"
    }
  ]
}

GET /api/dashboard/knowledge

Browse knowledge entries with pagination. Uses pgvector store when available, falls back to in-memory.

Authentication: Optional

Query Parameters:

Parameter Type Required Default Description
page integer No 1 Page number (1-based)
page_size integer No 20 Entries per page (1-100)
project string No null Filter by project

Response Body:

Field Type Description
entries array Knowledge entries for the current page
entries[].id string Entry ID
entries[].content string Entry content
entries[].user_id string or null User identifier
entries[].project string or null Project identifier
entries[].created_at string ISO 8601 timestamp
total integer Total number of entries
page integer Current page number
page_size integer Page size

Example:

curl "http://localhost:8000/api/dashboard/knowledge?page=1&page_size=10"
{
  "entries": [
    {
      "id": "a1b2c3d4e5f6",
      "content": "Example knowledge entry...",
      "user_id": null,
      "project": "docs",
      "created_at": "2026-03-08T12:00:00+00:00"
    }
  ],
  "total": 1,
  "page": 1,
  "page_size": 10
}

POST /api/dashboard/knowledge

Add a knowledge entry from the dashboard UI.

Authentication: Optional

Request Body:

Field Type Required Default Description
content string Yes Knowledge content text
user_id string No null User identifier
project string No null Project identifier

Response Body (201 Created):

Field Type Description
id string Entry ID
content string Stored content
user_id string or null User identifier
project string or null Project identifier
created_at string ISO 8601 timestamp

Example:

curl -X POST http://localhost:8000/api/dashboard/knowledge \
  -H "Content-Type: application/json" \
  -d '{"content": "New knowledge entry from dashboard", "project": "docs"}'
{
  "id": "b2c3d4e5f6a1",
  "content": "New knowledge entry from dashboard",
  "user_id": null,
  "project": "docs",
  "created_at": "2026-03-08T12:00:00+00:00"
}

DELETE /api/dashboard/knowledge/{entry_id}

Delete a knowledge entry from the dashboard.

Authentication: Optional

Path Parameters:

Parameter Type Description
entry_id string Entry ID (UUID for DB entries, short hex for in-memory)

Response: 204 No Content on success.

Example:

curl -X DELETE http://localhost:8000/api/dashboard/knowledge/a1b2c3d4e5f6

Error Responses:

Code Condition
404 Knowledge entry not found

GET /api/dashboard/cache

Cache performance statistics derived from audit data.

Authentication: Optional

Response Body:

Field Type Description
exact_hit_rate float Exact-match cache hit rate (0.0 to 1.0)
semantic_hit_rate float Semantic cache hit rate (0.0 to 1.0)
total_cached integer Total number of cached responses
estimated_savings_usd float Estimated cost savings from cache hits

Example:

curl http://localhost:8000/api/dashboard/cache
{
  "exact_hit_rate": 0.15,
  "semantic_hit_rate": 0.0,
  "total_cached": 45,
  "estimated_savings_usd": 1.23
}

10. Metrics

GET /metrics

Expose collected metrics in Prometheus exposition format. Includes counters, histograms, and gauges tracked by the ASGI telemetry middleware.

Authentication: None

Response: Plain text in Prometheus exposition format with content type text/plain; version=0.0.4.

Example:

curl http://localhost:8000/metrics
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="POST",path="/v1/chat/completions",status="200"} 1250
http_requests_total{method="POST",path="/v1/messages",status="200"} 430
# HELP http_request_duration_seconds HTTP request duration
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.1"} 200
http_request_duration_seconds_bucket{le="0.5"} 800
http_request_duration_seconds_bucket{le="1.0"} 1100
http_request_duration_seconds_bucket{le="+Inf"} 1250
http_request_duration_seconds_sum 625.4
http_request_duration_seconds_count 1250

Endpoint Summary

Method Path Auth Description
GET /health None Health check
GET /metrics None Prometheus metrics
POST /v1/chat/completions None OpenAI-compatible chat completions
POST /v1/messages Anthropic key Anthropic Messages API proxy
POST /v1/messages/count_tokens Anthropic key Anthropic token counting proxy
POST /v1/knowledge None Add knowledge entry
GET /v1/knowledge/search None Semantic knowledge search
DELETE /v1/knowledge/{entry_id} None Delete knowledge entry
POST /v1/knowledge/ingest None Bulk ingest knowledge
GET /v1/knowledge/topics None List knowledge topics
POST /v1/knowledge/consolidate Admin Trigger knowledge consolidation
POST /api/admin/projects Admin Create project
GET /api/admin/projects Admin List projects
POST /api/admin/keys Admin Create API key
GET /api/admin/keys Admin List API keys
DELETE /api/admin/keys/{key_id} Admin Deactivate API key
GET /api/dashboard/overview Optional Dashboard overview stats
GET /api/dashboard/costs Optional Cost breakdown
GET /api/dashboard/audit Optional Paginated audit log
GET /api/dashboard/pii Optional PII findings
POST /api/dashboard/knowledge/search Optional Dashboard knowledge search
GET /api/dashboard/knowledge Optional Browse knowledge entries
POST /api/dashboard/knowledge Optional Add knowledge (dashboard)
DELETE /api/dashboard/knowledge/{entry_id} Optional Delete knowledge (dashboard)
GET /api/dashboard/cache Optional Cache statistics
GET /api/dashboard/shadow Optional Shadow AI detection report
GET /api/dashboard/shadow/overview Optional Shadow AI overview
GET /api/dashboard/reports/pii-summary Optional PII summary report
GET /api/dashboard/reports/compliance Optional Full compliance report
GET /api/dashboard/reports/export Optional Export report (JSON/CSV)