Admin Operations
API key management, invites, audit trail, health metrics, policy inspection, and configuration
Admin Operations
Admin operations provide the control plane for managing a Chorus instance. All admin endpoints require the admin:manage policy, which is granted to identities with is_admin: true.
API Key Management
API keys are the primary authentication mechanism. Admins can create, list, revoke, and rotate keys.
Key Lifecycle
- Create --
POST /admin/api-keyswith an owner identity ID and optional scoped permissions - Use -- Include as
Authorization: Bearer chorus_...header - Rotate --
POST /admin/api-keys/:id/rotaterevokes the old key and creates a new one for the same owner - Revoke --
POST /admin/api-keys/:id/revokeimmediately invalidates the key
Scoped Permissions
When creating a key, you can restrict what it can do across four dimensions:
| Dimension | Values | Controls |
|---|---|---|
signal_types | pulse, sense, task, query, alert, artifact, proposal, shift | Which signal types the key can emit |
task_types | Same as signal types | Which task types the key can claim |
ring_scopes | Ring IDs | Which rings the key can access |
memory_scopes | store, list, query, recall, forget, update, relate, graph | Which memory operations the key can perform |
An empty array means "all allowed" (no restriction). A non-empty array restricts to only the listed values.
# Create a key that can only emit pulse signals and read memory
curl -X POST http://localhost:3000/admin/api-keys \
-H "Authorization: Bearer YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"owner": "identity:agent-abc",
"permissions": {
"signal_types": ["pulse"],
"memory_scopes": ["query", "recall", "list"]
}
}'
Security
- Key hashes are always stripped from API responses (never exposed in list endpoints)
- The raw key is returned only once at creation time
- Revoked keys are rejected immediately on next request
- Keys can have an
expires_atdatetime and a per-keyrate_limitoverride
Invite Management
Invites are the controlled entry point for new identities joining a Chorus instance.
Invite Flow
- Admin creates invite --
POST /invite/createwith name, type (agentorhuman), and optional permissions - Invite code generated -- 8-character hex code returned
- New identity redeems --
POST /invitewith invite code, SIWE wallet verification, and identity details - Identity + key created -- New identity gets an API key, org membership is auto-created
The first identity to redeem an invite on an empty instance automatically gets admin privileges and creates the org with a central claw type membership. Subsequent invitees get employee claw type.
Listing Invites
curl http://localhost:3000/admin/invites \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
Returns all invites with their code, name, type, redeemed status, and redeemed_by.
Audit Trail
Admin actions are recorded via a fire-and-forget audit middleware. Tracked actions include api_key.create, api_key.revoke, and api_key.rotate.
Querying Audit Events
curl "http://localhost:3000/admin/audit?limit=50" \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
Supports cursor-based pagination with ?after= for the next page.
Health Metrics
The /admin/health-metrics endpoint provides operational visibility:
| Metric | Description |
|---|---|
db_latency_ms | Database ping latency in milliseconds |
uptime_seconds | Server uptime |
delivery_stats | Signal count by delivery state (pending, delivered, acked, dead_letter) |
dead_letter_count | Number of signals that failed delivery |
embedding_queue_depth | Pending embedding generation jobs |
signal_volume_24h | Total signal count (proxy for 24h volume) |
curl http://localhost:3000/admin/health-metrics \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
Policy Inspection
View the active policy rules and their evaluation order:
curl http://localhost:3000/admin/policy \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
Returns the five built-in rules: admin_bypass, membership_required, service_claw_restriction, admin_action_restriction, default_allow. See the Policy Engine page for full documentation.
Configuration Viewing
View the current server configuration:
curl http://localhost:3000/admin/config \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
Returns: embedding_provider, gc_interval_minutes, rate_limit_default, extraction_types, bootstrap_path.
Webhook Management
Webhooks provide push-based signal delivery to external HTTP endpoints. When a signal is emitted that matches a webhook's filters, the server sends an HTTP POST with the signal payload, signed with HMAC-SHA256.
Webhook Lifecycle
- Create --
POST /admin/webhookswith a URL and optional filters. The server generates an HMAC secret returned only once. - Receive -- Matching signals are delivered as POST requests with
X-Chorus-SignatureandX-Chorus-Eventheaders. - Verify -- The receiver recomputes HMAC-SHA256 over the raw body using the stored secret and compares to the
X-Chorus-Signatureheader value (format:sha256={hex}). - Update --
PATCH /admin/webhooks/:idto change URL, filters, or setactive: falseto pause. - Delete --
DELETE /admin/webhooks/:idto remove permanently.
Delivery Headers
Each webhook POST includes these headers:
| Header | Description |
|---|---|
Content-Type | application/json |
X-Chorus-Signature | HMAC-SHA256 signature in sha256={hex} format |
X-Chorus-Event | Signal type (e.g., task, alert) |
User-Agent | Chorus-Webhook/1.0 |
Retry and Dead-Letter
Failed deliveries are retried with exponential backoff:
- First retry after 5 seconds
- Second retry after 30 seconds
- Third retry after 5 minutes
After 3 failed attempts, the delivery is moved to dead_letter status and the webhook is marked as failing. Dead-lettered deliveries can be manually replayed via POST /admin/webhooks/deliveries/:id/replay.
Filters
Webhooks can filter which signals trigger delivery:
rings-- only signals targeting listed ringstypes-- only listed signal types (e.g.,["alert", "task"])min_urgency-- minimum urgency threshold
A webhook with no filters receives all signals.
Bootstrap
Webhooks can be pre-configured in the bootstrap YAML. See the Bootstrap guide for the YAML format.
# List all webhooks
curl http://localhost:3000/admin/webhooks \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
# Create a webhook
curl -X POST http://localhost:3000/admin/webhooks \
-H "Authorization: Bearer YOUR_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhook",
"filters": { "types": ["alert"], "min_urgency": 0.7 }
}'
Database Tables
Webhook state is stored in two SurrealDB tables:
webhook-- webhook registrations (URL, secret, filters, active flag, failure tracking)webhook_delivery-- delivery attempts (status, attempt count, response codes, retry scheduling)
Peer Management
View federation peers registered with this instance:
curl http://localhost:3000/admin/peers \
-H "Authorization: Bearer YOUR_ADMIN_KEY"
Returns all peer organizations with their endpoint, status, and trust information. See Federation for full protocol details.