Bridge API Reference¶
This document lists all Bridge-owned HTTP endpoints. Component endpoints (Hippo, Cappella, Canon) are proxied through Bridge under their respective prefixes but are documented in each component's own API reference.
All endpoints are under the /api/v1/bridge/ prefix.
Authentication Endpoints¶
Issue token¶
Issue an access token. Supports Device Code callback and Client Credentials flows.
Request body (Client Credentials):
Request body (Device Code callback):
{
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": "...",
"client_id": "bass-cli"
}
Response (200):
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 900,
"refresh_token": "rt_..."
}
Refresh token¶
Exchange a refresh token for a new access token and refresh token pair.
Request body:
Response (200): Same shape as token issuance. The old refresh token is invalidated (rotation).
Revoke token¶
Revoke an access token (by jti) or a refresh token.
Request body:
Response (200):
Initiate Device Code flow¶
Start a Device Code authentication flow for CLI login.
Response (200):
{
"device_code": "...",
"user_code": "ABCD-1234",
"verification_uri": "https://idp.uni.edu/device",
"expires_in": 600,
"interval": 5
}
The CLI displays the user_code and verification_uri. The user opens the URI in
a browser, enters the code, and authenticates. The CLI polls the token endpoint with
the device_code until authentication completes.
API Key Endpoints¶
Create API key¶
Create a new API key. Requires admin role, or project_lead/analyst creating
a key for themselves.
Request body:
{
"label": "My notebook key",
"role": "analyst",
"project": "lab-a",
"expires": "2027-01-01T00:00:00Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | Yes | Human-readable key label |
role |
string | Yes | Role to assign (admin, project_lead, analyst, viewer, service) |
project |
string | No | Restrict key to a specific project |
expires |
string (ISO 8601) | No | Expiry date; no expiry if omitted |
Response (201):
{
"id": "key_01jx...",
"label": "My notebook key",
"secret": "bass_live_7f3a8b2c4d5e6f...",
"role": "analyst",
"project": "lab-a",
"expires": "2027-01-01T00:00:00Z",
"created_at": "2026-08-15T10:00:00Z",
"created_by": "alice@uni.edu"
}
The secret field is only returned in the creation response. It cannot be retrieved
after this.
List API keys¶
List API keys visible to the caller.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
all |
boolean | Admin only: list all users' keys (default: own keys only) |
user |
string | Admin only: filter by key owner |
Response (200):
{
"keys": [
{
"id": "key_01jx...",
"label": "My notebook key",
"role": "analyst",
"project": "lab-a",
"expires": "2027-01-01T00:00:00Z",
"created_at": "2026-08-15T10:00:00Z",
"last_used_at": "2026-08-20T14:30:00Z",
"created_by": "alice@uni.edu"
}
]
}
Note: secret is never included in list responses.
Revoke API key¶
Revoke an API key. The key stops working immediately.
Request body (optional):
Response (200):
Rotate API key¶
Atomically create a new key and revoke the old one. The new key inherits the same label, role, and project scope.
Response (200):
{
"new_key": {
"id": "key_01jy...",
"secret": "bass_live_9c8d7e6f...",
"label": "My notebook key",
"role": "analyst",
"project": "lab-a"
},
"revoked_key": {
"id": "key_01jx...",
"revoked_at": "2026-08-20T15:00:00Z"
}
}
Health and Observability¶
Platform health¶
Returns aggregated health status for Bridge and all registered components.
Response (200 or 503):
{
"status": "healthy",
"bridge": "healthy",
"components": {
"hippo": {
"status": "healthy",
"latency_ms": 3,
"url": "http://hippo:8001"
},
"cappella": {
"status": "healthy",
"latency_ms": 5,
"url": "http://cappella:8002"
},
"canon": {
"status": "degraded",
"latency_ms": 800,
"url": "http://canon:8003",
"detail": "slow_response"
}
},
"checked_at": "2026-08-15T10:30:00Z"
}
Status values:
| Status | HTTP code | Meaning |
|---|---|---|
healthy |
200 | All components responding within SLO |
degraded |
200 | One or more components slow or returning non-5xx errors |
unhealthy |
503 | One or more components unreachable or returning 5xx |
Results are cached with a 5-second TTL.
No authentication required. This endpoint is intended for load balancer and Kubernetes health probes.
Prometheus metrics¶
Returns Prometheus-compatible metrics. Enabled when observability.metrics.enabled: true
in bridge.yaml.
Key metrics:
| Metric | Type | Description |
|---|---|---|
bridge_requests_total |
Counter | Total requests by method, path prefix, status |
bridge_request_duration_seconds |
Histogram | Latency by method and path prefix |
bridge_auth_failures_total |
Counter | Auth failures by type |
bridge_component_health |
Gauge | 1 = healthy, 0 = unhealthy, per component |
bridge_sync_mismatches_total |
Counter | Sync mismatches by type |
bridge_active_tokens |
Gauge | Active refresh token count |
Sync Endpoints¶
List sync events¶
Query the sync event log for cross-component consistency events.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by resolution status: unresolved, resolved, all (default: all) |
limit |
integer | Max results (default: 50, max: 500) |
offset |
integer | Pagination offset |
Response (200):
{
"events": [
{
"id": "evt_...",
"event_type": "bridge.sync.mismatch",
"source": "cappella",
"source_id": "run_abc123",
"actor": "service:cappella-runner",
"details": {
"missing_entities": [
{"entity_type": "sample", "external_id": "EXT-099"}
]
},
"resolved": false,
"resolved_at": null,
"created_at": "2026-08-15T10:30:00Z"
}
],
"total": 1
}
Requires admin role.
Get sync event¶
Get details for a specific sync event. Requires admin role.
Resolve sync event¶
Mark a sync event as resolved. Requires admin role.
Request body:
Latest consistency scan¶
Get results of the most recent periodic consistency scan. Requires admin role.
Trigger consistency scan¶
Trigger an on-demand full consistency scan. Requires admin role.
Response (202):
Proxied Component Endpoints¶
Bridge forwards requests to component APIs under these prefixes. See each component's documentation for endpoint details.
| Prefix | Component | Example |
|---|---|---|
/api/v1/hippo/ |
Hippo (metadata tracking) | GET /api/v1/hippo/entities/sample |
/api/v1/cappella/ |
Cappella (workflow engine) | POST /api/v1/cappella/runs |
/api/v1/canon/ |
Canon (file cache) | GET /api/v1/canon/resolve |
Bridge strips the /api/v1/{component}/ prefix before forwarding. Components receive
requests on their own internal path scheme.
All proxied requests require authentication. Bridge injects X-Bass-Actor,
X-Bass-Roles, and X-Bass-Request-Id headers before forwarding.
Error Format¶
All Bridge-generated errors use a consistent JSON structure:
{
"error": "insufficient_role",
"message": "Role 'viewer' cannot perform 'entity:create'",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"details": {}
}
See Authentication for the full list of Bridge error codes.