Skip to main content

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 actor
  • action — filter by action type
  • agent — filter by agent name
  • since / until — RFC3339 timestamps
  • limit — 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 with Content-Disposition: attachment header
  • ?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

  • 400not_replayable (action is not query)
  • 403 — super_admin required
  • 422audit_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 .