Learn

Auth & API keys

Email-OTP provisioning, API key scopes (brain:read, brain:write, brain:admin, brain:act-as), key lifecycle, and per-user actor delegation.

Every request carries Authorization: Bearer <token> where the token is an API key with the prefix usk_. Only the provisioning endpoints are unauthenticated. The server is the only security boundary — clients never pre-check scopes.

Get a key (interactive)

unison auth login
# enter your email — new accounts get a key immediately (usage-capped)
# an OTP arrives by email and lifts the caps on verify

Raw HTTP:

# Provision a new account
curl -X POST https://brain.unisonlabs.ai/v1/auth/provision \
  -H "Content-Type: application/json" \
  -d '{ "email": "you@example.com" }'

# Verify OTP (lifts caps on new accounts; mints a new key on existing ones)
curl -X POST https://brain.unisonlabs.ai/v1/auth/verify \
  -H "Content-Type: application/json" \
  -d '{ "email": "you@example.com", "code": "123456" }'

Get a key (CI / machines)

export UNISON_TOKEN=usk_live_…    # set from a secret manager
# mint a dedicated key
unison auth keys create --name ci-deploy --scopes brain:read,brain:write

Scopes

ScopeUnlocks
brain:readall GETs, key listing, invitations
brain:writedocument write/delete/share, entity upsert, fact record/correct/invalidate, link
brain:admindedup review (merge/unmerge), job retry
brain:act-asactor delegation for per-end-user isolation

A token missing the required scope gets 403 forbidden. New keys can only carry a subset of the minting caller's scopes.

Key lifecycle

# List keys (never returns hashes)
curl 'https://brain.unisonlabs.ai/v1/auth/keys' \
  -H "Authorization: Bearer $UNISON_TOKEN"

# Create
curl -X POST https://brain.unisonlabs.ai/v1/auth/keys \
  -H "Authorization: Bearer $UNISON_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "ci-deploy", "scopes": ["brain:read", "brain:write"] }'
# token is returned once — store it immediately

# Revoke
curl -X DELETE 'https://brain.unisonlabs.ai/v1/auth/keys/<id>' \
  -H "Authorization: Bearer $UNISON_TOKEN"

Actor delegation (per-end-user isolation)

One service key can serve many end users. Each X-Unison-Actor id gets an automatically isolated /private/ namespace — no separate account needed per user:

import { BrainClient } from "@unisonlabs/sdk";

const service = new BrainClient({ token: process.env.UNISON_TOKEN });

const u1 = service.withActor("user-001");
await u1.write({ path: "/private/notes/chat.md", bodyMd: "user said …" });

const u2 = service.withActor("user-002");
await u2.search("what did I say?");   // isolated — no cross-actor leakage

The service key must carry brain:act-as. Shadow users are auto-created; each actor shares your workspace's /workspace/ namespace but has an isolated /private/. CLI: --actor <id> or UNISON_ACTOR=<id>.

Inspect the current key

curl 'https://brain.unisonlabs.ai/v1/auth/whoami' \
  -H "Authorization: Bearer $UNISON_TOKEN"
# returns: identity, workspaceId, scopes, actedAs (when delegation is active)

See also: Scopes & visibility · API reference

On this page