Authentication & API Keys
ContextNest Community distinguishes two kinds of key, and it is worth keeping them straight:
| Key | Prefix | What it is | Who holds it |
|---|---|---|---|
| API key | cnst_... |
A per-user credential that authenticates HTTP/MCP requests. | Every user; you can hold several. |
| License key | pk_... |
The instance's PromptOwl Community License. It licenses the server, not a request. | One per instance; owned by a PromptOwl account. |
A cnst_ key gets you in; the pk_ key is what keeps the server writable at
all. This page is about the cnst_ keys and how a request authenticates. For the
license see Self-Hosting (Community Edition).
How a request authenticates
The server accepts two methods, evaluated in order:
- Cookie session —
cnst_session=<id>, set byPOST /auth/loginandPOST /auth/register. This is the browser default. - Bearer API key —
Authorization: Bearer cnst_<token>, minted byPOST /auth/keys. Use this for scripts, service accounts, Postman, and remote CLIs.
curl -H 'Authorization: Bearer cnst_<your-token>' http://localhost:3838/nests
In AUTH_MODE=open most read endpoints bypass auth entirely — every request is
attributed to the anonymous admin user. In AUTH_MODE=key (the default for any
multi-user or internet-facing deployment) every request needs one of the two
methods above.
cnst_ API keys — the multiple-named-keys model
A user may hold several API keys — one per place they connect from — so
rotating the credential for one client doesn't disconnect the rest. The key
format is cnst_<64-hex>.
Minting a key — POST /auth/keys
{ "label": "cli", "nest_id": "optional — scope the key to one nest" }
labelis required. It must be unique among the caller's keys (compared case-insensitively, after trimming) and be at most 60 characters. Once the plaintext is gone the label is the only thing that tells two keys apart.400if the label is missing, blank, non-string, or over 60 chars.409on a duplicate label, or at the per-user ceiling of 20 keys.nest_id(optional) scopes the key to a single nest — a service-account credential. Omit it for a user-level key that works on every nest the user can access (this is what the Connect dialog mints). A nest-scoped key is rejected on any other nest's MCP/API paths.
The response returns the plaintext once:
{ "api_key": "cnst_...", "id": "uuid", "key_prefix": "cnst_abc123...", "label": "cli" }
Listing — GET /auth/keys
Returns the caller's keys (id, prefix, label, nest_id, created_at,
last_used_at), oldest first. Plaintext is never returned.
Rotating — POST /auth/keys/rotate
Replaces one key and returns its new plaintext; the caller's other keys are untouched.
{ "key_id": "uuid", "label": "optional", "nest_id": "optional" }
key_idnames the target. Omitting it is accepted only when the account holds exactly one key (pre-multi-key clients); with several keys and nokey_idthe server answers400rather than guessing.404if the id isn't the caller's.- Scope on
nest_id: absent → keep the prior scope;null(or"") → clear to a user-level key; a nest id → scope to that nest. - Label on rotate: absent keeps the prior label; a label matching a
different key of the caller's is
409; renaming a key to its current name is fine.
Revoking — DELETE /auth/keys/:keyId
Revokes one key; 404 if the id isn't the caller's. Anything still using it
stops working immediately.
Rotation is atomic and per-key. Because each connection carries its own named key, you rotate or revoke one credential without knocking the others offline. Rotate regularly on internet-facing deployments (
DELETE /auth/keys/:idthenPOST /auth/keys, orPOST /auth/keys/rotate).
The pk_ license key — different job
The pk_... key is not a request credential. It licenses the whole server:
- Unlicensed instances still boot and serve reads, but every write returns
503until a valid key is installed. - Install it via the browser License Setup Page or the
PROMPTOWL_KEYenv var (see Self-Hosting). - The admin identity follows the license — the admin user is whichever PromptOwl account owns the installed key, resolved live per request.
- A long-poll watcher tracks revocation; a revoked license blocks writes within seconds.
Never treat a pk_ key as an API token, and never send a cnst_ key where a
license is expected — they authenticate different things.
CLI / remote clients — env-var auth
The ctx CLI authenticates with a cnst_ key supplied through the environment,
not stored inline in commands. Mint a user-level key from the Connect dialog (or
POST /auth/keys with no nest_id), then hand it to the CLI:
-
Remote aliases (
ctx --vault <alias> …). There is no fixed variable name: you choose one when you register the server, and the registry stores only that name, never the key.export TEAM_NEST_TOKEN=cnst_... ctx vault add team --url https://nest.example.com/mcp --bearer-env TEAM_NEST_TOKENIf the named variable is unset at call time, the command fails with
CONFIG_ERRORinstead of calling the server unauthenticated. -
ctx pushreadsCONTEXTNEST_API_KEY.--key cnst_...also works but is visible to other processes and lands in shell history.
Scope the key to one nest (nest_id) for a locked-down service account. See
Remote & Governed Nests and
CLI Reference.
OIDC single sign-on
For human logins, Community Edition supports generic OpenID Connect SSO against any spec-compliant IdP (Microsoft Entra ID and Google are first-class presets; Okta / Keycloak work as standard issuers):
GET /auth/oidc/loginstarts an authorization-code flow with PKCE and redirects to your IdP.GET /auth/oidc/callbackverifies the returned ID token (issuer, audience, nonce, signature against the issuer's JWKS), then starts a normal browser session — identical to a password login.GET /auth/oidc/logoutperforms an RP-initiated logout where the IdP supports it.
Users are looked up by email; unknown emails are JIT-provisioned when
OIDC_AUTO_PROVISION is on, and OIDC_ALLOWED_DOMAINS can restrict which email
domains may sign in. Configure via the OIDC_* env vars or Settings → Single
sign-on (superadmin). OIDC sessions still act through the same session/cookie
mechanism as everything else.
PromptOwl native connection (service-ticket auth)
The official PromptOwl deployment can connect on its users' behalf without
storing a cnst_ key: it mints a short-lived HS256 service ticket signed
with the shared OFFICIAL_COMMUNITY_SSO_SECRET. The ticket carries
scope: "mcp", an aud bound to this server's PUBLIC_BASE_URL, a ~5-minute
exp, and no jti; it resolves to an already-existing account by email (native
access never auto-provisions). It is accepted as a Bearer on the MCP retrieval
paths only. On self-hosted servers OFFICIAL_COMMUNITY_SSO_SECRET is unset, so
this path is inert and you use a real cnst_ key. See
Connect an Agent.
Related
- CLI Reference —
ctx pushandctx vault add --bearer-env - REST API Reference — the
/auth/*endpoints in context - Self-Hosting (Community Edition) — auth modes and the license
- Connect an Agent (MCP) — using a key over MCP
Sources
API.md(Community server repo) — §1 Auth (/auth/keys*, register, login, invite, OIDC) and §9 MCP (PromptOwl native connection / service tickets).CONFIGURATION.md(Community server repo) —AUTH_MODE,PROMPTOWL_KEY, theOIDC_*vars, andOFFICIAL_COMMUNITY_SSO_SECRET.README.md(Community server repo) — the "several API keys per account" feature and license behaviour.packages/cli/src/index.tsandpackages/engine/src/registry.ts(ContextNest repo) —ctx pushkey handling and remotebearer_envauth.
Related pages
- CLI ReferenceThe Context Nest CLI (ctx) is a structured, versioned knowledge base your AI agents can query. It provides commands for setting up vaults, creating and…
- Remote & Governed NestsA nest does not have to live on your local disk. ContextNest can register remote nests and route reads and writes to them over MCP — the same ctx commands…
- REST API ReferenceA concise reference to the ContextNest Community (hosted-nest) REST API. It is faithful to the server's API.md; only endpoints that actually exist are…
- Self-Hosting (Community Edition)ContextNest Community Edition is a self-hosted context governance server for AI workflows, part of the PromptOwl platform. It stores, versions, and…
- Connect an Agent (MCP)A hosted nest speaks the Model Context Protocol (MCP), so any MCP-capable AI agent — Claude Desktop, Claude Code, Cursor, and others — can connect and…