Management API

Contexts, keys, and operator lifecycle.

The management API provides control-plane operations: creating Contexts, managing API keys, and operator lifecycle. All management endpoints are under /api/v1/ and require a management key.

Management endpoints require a management API key as a Bearer token:

Authorization: Bearer <management-key>

Keys are printed once by bootstrap or minted via spectrond keys generate-key / management REST. They are distinct from per-Context end-user keys.

GET /api/v1/contexts

Returns all Contexts registered on this Spectron deployment.

Response:

{
"contexts": [
{
"id": "acme-prod",
"namespace": "acme",
"database": "prod",
"config": {
"token_limit": 1000000,
"models": { "extraction": "openai/gpt-4o-mini" },
"providers_configured": ["openai"]
},
"created_at": "2026-01-15T10:00:00Z"
}
]
}
POST /api/v1/contexts/{context_id}
Content-Type: application/json

{
"namespace": "acme",
"database": "prod",
"admin_external_id": "surreal-cloud:usr_01HF…",
"admin_display_name": "Alice Admin",
"config": {
"token_limit": 1000000,
"models": {
"extraction": "openai/gpt-4o-mini",
"response": "openai/gpt-4o"
},
"providers": {
"openai": "sk-..."
}
}
}

Creates the Context, provisions the SurrealDB namespace and database, and applies schema migrations. Returns 201 Created.

When admin_external_id is set, Spectron seeds an initial principal:admin bound to that opaque, issuer-qualified identity (for example surreal-cloud:<user_id>) with full /* grants — so a Cloud proxy can create a Context and immediately resolve the org owner without a follow-up principal call. admin_display_name is an optional human-readable label. Omit both fields to keep the generic admin principal.

Response:

{
"id": "acme-prod",
"namespace": "acme",
"database": "prod",
"config": {
"token_limit": 1000000,
"models": { "extraction": "openai/gpt-4o-mini" },
"providers_configured": ["openai"]
},
"created_at": "2026-05-12T10:00:00Z"
}
GET /api/v1/contexts/{context_id}

Returns the Context record. Provider API key values are replaced with a providers_configured summary (per-Context keys only). For the full provider and model catalogue — including providers reachable via deployment-wide keys — use GET /api/v1/{context_id}/providers on the data-plane API.

PATCH /api/v1/contexts/{context_id}
Content-Type: application/json

{
"config": {
"token_limit": 2000000,
"models": {
"reflection": "anthropic/claude-opus-4-7"
}
}
}

Deep-merges the provided config into the existing config. Unset fields are left unchanged.

DELETE /api/v1/contexts/{context_id}

Drops the bound SurrealDB database (removing all authoritative knowledge and experiential memory data), deletes the associated API keys, and removes the control-plane registry entry. This is irreversible. Returns 204 No Content.

Spectron authorises data-plane and admin operations with seven scoped verbs in <noun>:<verb> form:

VerbPurpose
memory:readRead facts and document chunks/keywords within the granted region (recall, query, chat, document GET/list)
memory:writeWrite facts and ingest documents (chunks inherit the uploader’s write region)
memory:forgetSoft or hard forget, entity delete, scoped subtree erasure
scope:readList scope names visible within the grant (does not imply data access)
scope:createRegister new scope paths
scope:deleteRemove scope paths
grant:manageGrant or revoke access on principals

Documents are governed by memory:* verbs — there is no separate document:* namespace. Upload and reprocess require memory:write; document reads are per-row under memory:read.

List the machine-readable catalog (for grant pickers and validation):

GET /api/v1/verbs
Authorization: Bearer <management-key>

Grant verbs use namespaced forms (memory:read, memory:write, …). Flat names such as read and write are rejected.

Principals are the data-plane identity Spectron authorises. Create one with an optional external_id so upstream systems (SurrealDB Cloud, OIDC, on-prem IdP) can resolve “which principal is this user?” without a side mapping table:

POST /api/v1/contexts/{context_id}/principals
Content-Type: application/json

{
"display_name": "Alice",
"external_id": "surreal-cloud:usr_01HF…",
"grants": {
"memory:read": [{ "org": "acme", "user": "alice" }],
"memory:write": [{ "org": "acme", "user": "alice" }]
}
}

When external_id is present, create is create-or-get: a repeat call with the same issuer-qualified id returns the existing principal unchanged (even if display_name differs). Without external_id, each call mints a fresh principal. The value is opaque to Spectron — qualify it with your issuer prefix.

Every Context seeds two reserved principals:

PrincipalPolicy
principal:systemFully immutable — update, grant change, and delete all return 403. Background jobs stamp provenance against this identity.
principal:adminUndeletable (delete returns 403) but otherwise mutable — rename, re-kind, and grant changes are allowed. Recovery from a broken admin grant map uses the control-plane management key, which is independent of this data-plane principal.

Grant changes and key minting for ordinary principals enforce attenuation only at the store layer: key grants must be a subset of the bound principal's grants on every mint path (management nested mint and self-service POST /keys).

Data-plane keys are always bound to a principal. Mint them under that principal on every path (management nested mint, Cloud broker, or self-service POST /{ctx}/keys). Keys with no principal binding are rejected with 401.

POST /api/v1/contexts/{context_id}/principals/{principal_id}/keys/{key_name}?ttl_seconds=2592000
Content-Type: application/json

{
"grants": {
"memory:read": [{ "org": "acme", "agent": "planner" }]
}
}

Optional grants in the body attenuate (narrow) the principal’s grants per verb (intersect only — widening returns 400). Omit grants to inherit the principal’s full region. The secret is returned once.

Duplicate key names within a Context return 409 Conflict (names are unique per Context, not per principal).

GET /api/v1/contexts/{context_id}/principals/{principal_id}/keys

Each entry includes id, name, and optional grants — the per-key attenuating grant map. When grants is omitted, the key inherits the principal's grants wholesale; when present, it only narrows per verb.

POST   /api/v1/contexts/{context_id}/principals/{principal_id}/keys/{key_name}/rotate?ttl_seconds=2592000
DELETE /api/v1/contexts/{context_id}/principals/{principal_id}/keys/{key_name}

On nested rotate/delete, a key that does not exist, is unbound, or belongs to a different principal returns 404 (no cross-principal leakage).

Flat list endpoints remain for operators auditing all keys in a Context:

GET    /api/v1/contexts/{context_id}/keys
DELETE /api/v1/contexts/{context_id}/keys/{key_name}
POST /api/v1/contexts/{context_id}/keys/{key_name}/rotate?ttl_seconds=2592000

List responses include optional grants on each key (same semantics as the principal-nested list).

The secret is never returned after creation except on mint and rotate.

Principal types:

PrincipalCapabilities
agentCreate sessions, add turns, recall context, search knowledge. Cannot persist reflections or manage keys.
supervisorAll agent capabilities plus persisting reflections within the supervisor’s grant region.

For Surrealist and other Cloud proxies that must mint a short-lived, member-scoped key in one round-trip without handing every member a management key:

POST /api/v1/contexts/{context_id}/access-tokens
Content-Type: application/json

{
"external_id": "surreal-cloud:usr_01HF…",
"display_name": "Alice",
"ttl_seconds": 3600,
"grants": {
"memory:read": [{ "org": "acme", "user": "alice" }],
"memory:write": [{ "org": "acme", "user": "alice" }]
}
}

Composes create-or-get principal by external_id, optional grant re-assertion, and mint a bound key. ttl_seconds is required — brokered tokens cannot be unbounded. Re-broker before expiry; there are no refresh tokens. The plaintext secret is returned once.

Member-facing self-service key management (after a brokered or admin-minted key is held) lives on the REST API — not the management API.

Document ingestion requires a management key or an agent key with explicit upload capability. See Uploading documents for the full upload API.

POST /api/v1/{context_id}/documents
Content-Type: multipart/form-data
Authorization: Bearer <key>

file=@document.pdf
title=Product Catalogue
scope[org]=acme

Ontology endpoints (entity type definitions, attribute key declarations, and relation label declarations) are management-only. See Ontology grounding for details.

GET    /api/v1/contexts/{context_id}/ontology
PUT /api/v1/contexts/{context_id}/ontology
DELETE /api/v1/contexts/{context_id}/ontology

Runs the lifecycle decay pass immediately, expiring context-category memories past their TTL and pruning expired semantic cache entries:

POST /api/v1/contexts/{context_id}/lifecycle/decay

Triggers re-embedding and re-indexing of all chunks in a Context (e.g. after changing the embedding model):

POST /api/v1/contexts/{context_id}/lifecycle/reindex

This is a long-running operation. Poll the returned job ID to track progress.

List endpoints support cursor-based pagination:

GET /api/v1/contexts/{context_id}/keys?cursor=cak_01HF...&limit=20

Response:

{
"keys": [...],
"next_cursor": "cak_01HG...",
"has_more": true
}

next_cursor is null and has_more is false when the last page has been reached.

Was this page helpful?