molecule-core/docs/guides/org-api-keys.md
Hongming Wang 3d7244ab94 feat(auth): org tokens reach /workspaces/:id/* subroutes + docs
Extends WorkspaceAuth to accept org API tokens as a valid
credential for any workspace sub-route in the org. Previously a
user minting an org token could hit admin-surface endpoints
(/workspaces, /org/import, etc.) but couldn't reach per-workspace
routes like /workspaces/:id/channels — those were gated by
WorkspaceAuth which only knew about workspace-scoped tokens.

Scope matches the explicit product spec: one org API key can
manipulate every workspace in the org. AI agents given a key can
read/write channels, tokens, schedules, secrets, tasks across all
workspaces.

## WorkspaceAuth tier order

  1. ADMIN_TOKEN exact match (break-glass / bootstrap)
  2. Org API token (Validate against org_api_tokens)           NEW
  3. Workspace-scoped token (ValidateToken with :id binding)
  4. Same-origin canvas referer

Org token tier sits above the per-workspace check so a presenter
of an org key doesn't hit the narrower ValidateToken failure path
first. Checked with isSameOriginCanvas path unchanged.

## End-to-end verified

Minted test token via ADMIN_TOKEN, then with that org token:
  - GET /workspaces             → 200 (list all)
  - GET /workspaces/<id>        → 200 (detail, admin-only route)
  - GET /workspaces/<id>/channels → 200 (workspace sub-route)
  - GET /workspaces/<id>/tokens   → 200 (workspace tokens list)
  - GET /workspaces/<bad-uuid>    → 404 workspace not found
                                    (routing still scoped correctly)

## Documentation

  - docs/architecture/org-api-keys.md — design, data model, threat
    model, security properties
  - docs/architecture/org-api-keys-followups.md — 10 tracked
    follow-ups prioritized (role scoping P1, per-workspace binding
    P1, expiry P2, usage metrics P2, WorkOS user_id capture P2,
    rotation webhooks P3, mint-rate limit P3, audit log P2, CLI
    P3, migrate ADMIN_TOKEN to the same table P4)
  - docs/guides/org-api-keys.md — end-user guide (mint via UI,
    use in curl/Python/TS/AI agents, session-vs-key comparison)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 14:11:45 -07:00

4.4 KiB

Organization API Keys — User Guide

Full-admin API keys for your Molecule AI organization. Use these to let AI agents, scripts, or integrations manage your org without a browser session.

TL;DR

  1. Open your org's canvas UI (https://<your-slug>.moleculesai.app)
  2. Settings (⌘,) → Org API Keys tab
  3. Click New Key, give it a label (e.g. "zapier", "my-claude-agent")
  4. Copy the token immediately — it will never be shown again
  5. Hand it to whatever needs org-admin access:
    Authorization: Bearer <your-token>
    

Revoke from the same UI the moment anything looks wrong.

What these keys can do

Full organization admin. A valid org API key is equivalent to being logged in as an admin user. With it, a script or AI can:

  • Create, delete, list workspaces
  • Import a complete org definition (can wipe + recreate everything)
  • Manage per-workspace secrets (your OpenAI/Anthropic/etc. keys)
  • Register + install templates, bundles, plugins
  • Approve or reject pending workspace approvals
  • Configure channels (Slack, Discord, etc.)
  • Mint more org API keys
  • Revoke any org API key (including itself)

What they cannot do:

  • Reach the control plane's admin API (/cp/admin/*) — CP admin lives on a separate allowlist.
  • Touch other organizations — each org's keys work only on its own tenant.
  • Edit the tenant's environment variables or restart the underlying EC2 instance — those are ops-only operations.

Treat keys like passwords

  • Don't commit keys to git. If you must have one in source, reference an env var and keep the var in your secret manager.
  • Don't paste keys into Slack or email. Share via a password manager when you can.
  • Do give each integration its own key with a descriptive name. If Zapier gets compromised, you revoke zapier and leave github-action-deploy untouched.
  • Do revoke any key you stop using.

If you leak one, revoke it and mint a new one. Revocation is immediate — the next request with the old key gets 401.

Using a key

curl

curl -H "Authorization: Bearer $MOLECULE_ORG_TOKEN" \
  https://acme.moleculesai.app/workspaces

Python

import os, requests

resp = requests.get(
    "https://acme.moleculesai.app/workspaces",
    headers={"Authorization": f"Bearer {os.environ['MOLECULE_ORG_TOKEN']}"},
)
resp.raise_for_status()
print(resp.json())

TypeScript / Node

const resp = await fetch("https://acme.moleculesai.app/workspaces", {
  headers: { Authorization: `Bearer ${process.env.MOLECULE_ORG_TOKEN}` },
});
if (!resp.ok) throw new Error(`${resp.status}: ${await resp.text()}`);
console.log(await resp.json());

Hand it to an AI agent

Add the key to the agent's environment or config, with clear instructions about what routes it should touch. Claude Code, for example, can use it to inspect the tenant's state programmatically:

export MOLECULE_ORG_TOKEN=...   # the key you just minted

Then tell the agent: "Using MOLECULE_ORG_TOKEN, list my workspaces and tell me which ones are idle."

Endpoints you'll hit most often

Method Path What it does
GET /workspaces list all workspaces
POST /workspaces create a workspace
DELETE /workspaces/:id delete a workspace
GET /org/templates list registered templates
POST /org/import import a full org YAML
POST /bundles/import install a bundle
GET /approvals/pending list pending approvals

Each workspace you create gets its own workspace-scoped token returned in the create response. Use that token (not the org key) for agent-to-platform calls inside that specific workspace — it has a narrower blast radius if leaked.

Full API reference: docs/api-reference.md.

Keys vs session cookies

Org API Key WorkOS session cookie
Who holds it Integrations, AI, CLI Your browser
Where you see it /org/tokens UI Browser cookies
Revocation One-click in UI Log out / session expiry
Use from code Yes No (HttpOnly)
Blast radius Full org admin Full org admin

Both unlock the same surface; the key is just the non-browser equivalent.

What's coming

Scoped roles (READ / WORKSPACE-WRITE / ORG-ADMIN), expiry timers, per-workspace bindings, and usage metrics are on the roadmap. See docs/architecture/org-api-keys-followups.md. For now every key is full-admin by design — trading scope granularity for beta shipping speed.