Provisioning
Create tenants and workspaces, manage workspace grants and mint or revoke API keys programmatically through the control-plane API.
Most teams create workspaces and keys in the web console. When another system needs to do it — a platform that gives each of its customers a memory workspace, for example — use the control-plane API under /api/control. It is idempotent: every operation is a PUT to a caller-chosen ID, or a mint/revoke.
Not part of /v1
The control plane is a separate surface from the /v1 data plane. It lives at /api/control/..., is not versioned under /v1, and does not emit deprecation headers.
Who can call it
Control-plane calls need a token from an integration service principal — a machine client of the identity provider your deployment is configured with (Auth:Authority), issued for the admin audience (Auth:AdminAudience) — or a platform operator. Each endpoint requires one of three scopes:
| Scope | Allows |
|---|---|
tenant:provision | Create or rename tenants |
workspace:provision | Create or rename workspaces |
grant:manage | Manage workspace grants and API keys |
Every operation is also bounded by the integration's grants on the platform side: an integration may create new tenants only if it holds an umbrella grant, and it can manage only the tenants it created. Anything else answers 404 — a leaked integration token cannot see or touch another integration's tenants.
| Method | Path | Scope |
|---|---|---|
PUT | /api/control/tenants/{tenantId} | tenant:provision |
PUT | /api/control/tenants/{tenantId}/workspaces/{workspaceId} | workspace:provision |
PUT | /api/control/workspaces/{workspaceId}/grants/{userId} | grant:manage |
DELETE | /api/control/workspaces/{workspaceId}/grants/{userId} | grant:manage |
POST | /api/control/workspaces/{workspaceId}/keys | grant:manage |
DELETE | /api/control/keys/{keyId} | grant:manage |
Create or rename a tenant
PUT /api/control/tenants/{tenantId}
{ "name": "Acme Corp" }201 with { "id", "name" } when created; 200 when an existing tenant you own was renamed. The integration automatically gets an ownership grant on the new tenant.
Create or rename a workspace
PUT /api/control/tenants/{tenantId}/workspaces/{workspaceId}
{ "name": "support-bot-prod", "selfGrant": true }201 with { "workspaceId", "name" } when created; 200 on rename. With selfGrant: true (the default) the integration also receives a grant on the new workspace — read, write, feedback and curate; delete stays off — so it can use the workspace immediately with a data-plane token. A workspace ID already used by another tenant answers 404.
Upsert a grant
PUT /api/control/workspaces/{workspaceId}/grants/{userId} — give a provisioned user access to a workspace, or change it.
{
"canRead": true,
"canWrite": true,
"canFeedback": true,
"canCurate": false,
"canDelete": false,
"canShare": false,
"canPromote": false,
"agentIds": ["support-bot"],
"canActForUsers": false
}The five core capabilities are required booleans. agentIds and canActForUsers set the grant's identity binding; omit them to leave the existing binding unchanged. Returns 200 { userId, workspaceId }. Changes take effect on the very next request on every replica.
Revoke a grant
DELETE /api/control/workspaces/{workspaceId}/grants/{userId} → 204. Effective on the next request.
Mint an API key
POST /api/control/workspaces/{workspaceId}/keys
{
"label": "support-bot-prod",
"agentIds": ["support-bot"],
"canActForUsers": true,
"canRead": true,
"canWrite": true,
"canFeedback": true,
"canCurate": true,
"canDelete": false,
"canShare": false,
"canPromote": false,
"expiresAt": "2027-10-01T00:00:00Z"
}| Field | Default | Notes |
|---|---|---|
label | api-key | Shown in the console. |
agentIds | none | Agents the key may act as; the first is the default. Without any, the key acts only as itself. |
canActForUsers | false | Allow the key to name end users (userId). |
canRead, canWrite, canFeedback, canCurate | true | |
canDelete, canShare, canPromote | false | |
expiresAt | none | Optional expiry. |
Response — the plaintext key is returned exactly once:
{ "keyId": "…", "key": "amk_…", "prefix": "amk_AbCdEfGh", "workspaceId": "…" }Only a SHA-256 hash of the key is stored. A plan's active-key cap applies (429 QUOTA_EXCEEDED when reached).
Revoke an API key
DELETE /api/control/keys/{keyId} → 204. The key stops working immediately on every replica.
Invites
Tenant administrators can also invite people by email:
POST /v1/tenants/{tenantId}/inviteswith{ "email", "workspaceId"?, "role"?, "canRead"?, "canWrite"?, … }—roleismember(default) ortenant-admin. Returns201 { inviteId, code, expiresAt }.POST /v1/invites/claimwith{ "code" }— the invited person claims the invite with their own signed-in identity token. A verified email is required.
Without an identity provider
On a self-hosted deployment without an identity provider, use the API host's one-shot commands instead:
--bootstrap-keycreates a tenant, a workspace and one agent-bound key.--provision-tenant <spec.json>provisions a tenant with workspaces, applications, keys and tenant admins from a JSON spec, idempotently.
See Deployment.