Administration
All /admin endpoints require an admin or super_admin human access token. Agent JWTs are explicitly rejected even if they carry an admin role claim.
System status
GET /admin/status
Reports process health for daemon components.
{
"orchestrator": "up",
"api": "up",
"utils": "down"
}
User management
GET /admin/users
List all users.
POST /admin/users
Create a user. Validates against the configured password policy. Checks the seat quota from the license (super_admin bypasses).
{
"username": "alice",
"password": "Str0ng!Pass",
"role": "user"
}
Valid roles: admin, user, viewer, operator.
Returns 402 with a QuotaExceededBody when the seat limit is reached.
PATCH /admin/users/{id}
Update role and/or disabled status. The id parameter is the username (not UUID).
Cannot demote or disable the last active admin — doing so would re-open /auth/setup to unauthenticated callers.
{ "role": "viewer", "disabled": false }
DELETE /admin/users/{id}
Cannot delete the last active admin.
POST /admin/users/{id}/reset-password
{ "password": "NewStr0ng!Pass" }
GET /admin/users/{id}/passkeys
List passkey credentials for a user (credential IDs only; no public key material exposed).
DELETE /admin/users/{id}/passkeys/{cred_id}
Revoke a specific passkey. Returns 204.
Audit log
The audit log is an append-only, HMAC-chained table. Every significant action writes a row. The chain integrity can be verified independently.
GET /admin/audit
Cursor-based pagination. Returns up to 100 entries per page (configurable with ?limit=N).
Query params
principal— filter by actoraction— filter by action typeagent— filter by agent namesince/until— RFC3339 timestampslimit— page size (default 100)after_id— cursor (resume from this audit entry ID)
Response 200
{
"entries": [
{
"id": "01HXZ...",
"principal": "alice",
"action": "query",
"agent": "researcher",
"session": "my-session",
"metadata": "{\"replay_inputs\":{...}}",
"created_at": "2026-01-15T14:32:00Z",
"tenant_id": "default",
"prev_hash": "abc...",
"row_hash": "def..."
}
],
"next_cursor": "01HXZ..."
}
GET /admin/audit/verify
Verifies HMAC chain integrity across all audit rows.
GET /admin/audit/export
Requires audit_export license entitlement.
Bulk export up to 50,000 rows. Same filter params as /admin/audit.
?format=csv— CSV withContent-Disposition: attachmentheader?format=json(default) — newline-delimited JSON (ndjson)
curl "http://localhost:8080/admin/audit/export?format=csv&since=2026-01-01T00:00:00Z" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-o audit-export.csv
POST /admin/audit/{id}/replay
Requires super_admin role.
Re-executes the original query that produced the referenced audit entry. Only action == "query" rows with a valid replay_inputs block are replayable.
Emits an audit.replay row on success.
Response 200
{
"audit_id": "01HXZ...",
"replayed_at": "2026-05-14T12:00:00Z",
"output": "The capital of France is Paris.",
"session_id": "my-session"
}
Errors
400—not_replayable(action is notquery)403— super_admin required422—audit_inputs_missing(no replay_inputs block in metadata)
License
GET /admin/license
Always returns 200. Community license is the default.
{
"tier": "enterprise",
"customer": "Acme Corp",
"kid": "key-2026",
"issued_at": "2026-01-01T00:00:00Z",
"expires_at": "2027-01-01T00:00:00Z",
"entitlements": ["oidc", "scim", "multi_tenant", "audit_export"],
"days_remaining": 232,
"expired": false,
"expired_grace_remaining_seconds": 0,
"max_seats": 100,
"current_seats": 12,
"max_tenants": 50,
"current_tenants": 3
}
Telemetry preferences
GET /admin/telemetry/preferences
Returns the global telemetry opt-in preference (default false — opt-in).
PUT /admin/telemetry/preferences
{ "enabled": true }
Diagnostics
GET /admin/diagnostics
Surfaces live observability state without requiring log access or exec into a pod.
{
"otel": {
"exporter_configured": true,
"endpoint": "http://otel-collector:4318",
"service_name": "alexandria-api",
"service_version": "0.1.0"
},
"orchestrator": {
"socket_path": "/home/user/.alexandria/run/orchestrator.sock",
"connected": true,
"last_reload": {
"at": "2026-05-14T11:30:00Z",
"backends_loaded": 3,
"duration_ms": 42
}
},
"sync_loop": {
"running": true,
"interval_seconds": 30,
"last_tick_at": "2026-05-14T11:30:00Z"
}
}
Changesets
Changesets allow config-diff tracking with rollback support. Useful for auditing configuration changes.
GET /admin/changesets
POST /admin/changesets
{ "notes": "Add three new LLM backends" }
GET /admin/changesets/{id}
POST /admin/changesets/{id}/entries
Append an entry to a pending changeset. Returns 409 if the changeset is already promoted or rolled back.
{
"operation": "add_backend",
"payload": "{\"name\":\"gpt4o\",\"url\":\"...\"}"
}
POST /admin/changesets/{id}/promote
Promotes and replays the changeset. Marks it as promoted and runs all entries. Returns 409 if already promoted.
POST /admin/changesets/{id}/rollback
Marks the changeset as rolled back.
Notifications
GET /admin/notifications/config
Returns the current notification sink configuration. Secret values are never included — only presence is reported.
{
"webhook_url": "https://hooks.slack.com/...",
"webhook_secret_set": true,
"alertmanager_url": "",
"alertmanager_severity": "critical",
"reconcile_interval_seconds": 60
}
PATCH /admin/notifications/config
Requires super_admin. Hot-swaps the notifier without restart.
{
"webhook_url": "https://hooks.slack.com/...",
"reconcile_interval_seconds": 30
}
POST /admin/notifications/test
Requires super_admin. Fires a synthetic test notification to all configured sinks.
curl examples
# List users
curl http://localhost:8080/admin/users \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq .
# Audit with filter
curl "http://localhost:8080/admin/audit?action=query&since=2026-01-01T00:00:00Z&limit=20" \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq .
# Check license
curl http://localhost:8080/admin/license \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq .
# Diagnostics
curl http://localhost:8080/admin/diagnostics \
-H "Authorization: Bearer $ADMIN_TOKEN" | jq .