docs: Platform Management API developer guide #57

Merged
devops-engineer merged 4 commits from docs/platform-management-api into main 2026-06-01 09:49:02 +00:00
7 changed files with 802 additions and 0 deletions
+1
View File
@@ -15,6 +15,7 @@
"external-agents",
"tokens",
"api-reference",
"platform-management-api",
"mcp-server",
"self-hosting",
"self-hosting/admin-token",
@@ -0,0 +1,154 @@
---
title: Auth Model
description: Every Molecule management credential — WorkOS session, CP admin bearer, provision secret, Org API Key, per-workspace token, ADMIN_TOKEN — how to obtain each, and the credential → route tier matrix.
---
# Auth Model
Molecule's management surface spans [two services](/docs/platform-management-api#the-one-structural-fact-two-services-two-auth-stacks),
each with its own auth stack. This page enumerates every credential type, how
to obtain it, and exactly which routes it authorizes.
## The six credential types
### 1. WorkOS session cookie
- **Service:** Control plane (`api.moleculesai.app`).
- **What it is:** the browser AuthKit session set after a user signs in through
the dashboard. Carries user identity and org ownership/membership.
- **How to obtain:** sign in via `/auth/login` (AuthKit/WorkOS); the session
cookie is set by the `/auth/callback` redirect. The dashboard sends it
automatically.
- **Authorizes:** the human-owner CP surface — create/delete orgs, manage
members, billing, and (proxied) tenant operations. This is the dashboard's
credential, not a headless-integration credential.
- **Header:** sent as a cookie, plus `X-Molecule-Org-Slug` for org-scoped
routes.
### 2. CP admin bearer (`CP_ADMIN_API_TOKEN`)
- **Service:** Control plane, `/api/v1/admin/*` (`/cp/admin/*` is the older,
identical alias).
- **What it is:** the platform-operator master token for fleet operations.
- **How to obtain:** set as an environment variable on the control plane; held
by platform operators only. Not user-facing.
- **Authorizes:** fleet ops, tenant teardown, force-setting workspace env,
image/AMI pins, reapers, beta allowlist. (LLM billing-mode is **not** a CP
route — it lives on the tenant, behind an Org API Key.)
- **Header:** `Authorization: Bearer <CP_ADMIN_API_TOKEN>`.
<Callout type="warn">
The CP admin bearer is platform-root. It is **not** the Org API Key and **not**
the tenant `ADMIN_TOKEN`. Keep it out of per-org integrations entirely.
</Callout>
### 3. Provision shared-secret (+ tenant-admin-token)
- **Service:** Control plane, `/api/v1/workspaces/provision|:id` (the
`/cp/workspaces/*` prefix is the older, identical alias).
- **What it is:** a shared secret that gates the EC2-side provisioning path.
Deprovision additionally requires the target org's tenant-admin-token.
- **How to obtain:** provisioning is normally driven by the platform itself;
the tenant-admin-token for an org is read from CP admin
(`GET /api/v1/admin/orgs/:slug/admin-token`, CP-admin-bearer gated).
- **Authorizes:** only `POST /api/v1/workspaces/provision`,
`DELETE /api/v1/workspaces/:id`, and `GET …/status`. Nothing else.
- **Header:** the provision secret as `Authorization: Bearer <secret>`.
Deprovision adds the per-tenant admin token in **`X-Molecule-Admin-Token`**
(not `Authorization`, not `X-Molecule-Org-Id`).
### 4. Org API Key (`org_api_tokens`) — the common one
- **Service:** Tenant (`<org-slug>.moleculesai.app`).
- **What it is:** a named, sha256-hashed, prefixed, revocable token that grants
**full tenant-admin** over its own org. This is the credential behind
dashboard **Settings → Org API Keys**.
- **How to obtain:** mint via the dashboard, or
`POST /org/tokens` on the tenant host (authorized by an existing Org API Key,
`ADMIN_TOKEN`, or a CP session). The plaintext is shown **once**. See
[Getting started](/docs/platform-management-api/getting-started).
- **Authorizes:** the entire tenant-admin surface of its org — workspaces
(list/create/delete/restart), secrets (workspace and org), per-workspace
billing-mode and budget, templates,
bundles, org tokens, plugin allowlist. **Reaches nothing on the CP.**
- **Header:** `Authorization: Bearer <key>` **and** `X-Molecule-Org-Id: <orgId>`
to the tenant host.
<Callout type="warn">
An Org API Key can **mint and revoke other Org API Keys**. Treat it as tenant
root. There is no scope-down below full-admin today. See the
[security note](/docs/platform-management-api/getting-started#security-tenant-root).
</Callout>
### 5. Per-workspace token
- **Service:** Tenant, `/workspaces/:id/*`.
- **What it is:** a bearer token bound to a **single** workspace; a token for
workspace A cannot touch workspace B.
- **How to obtain:** issued during workspace registration
(`POST /registry/register`). Two mint routes exist:
`POST /workspaces/:id/tokens` (WorkspaceAuth — self-service, from a token
already bound to that workspace) and `POST /admin/workspaces/:id/tokens`
(AdminAuth — Org API Key / `ADMIN_TOKEN`, the route the management MCP/CLI
uses). List with `GET /workspaces/:id/tokens`. See
[Token Management API](/docs/guides/token-management).
- **Authorizes:** run/secrets/config/restart on the bound workspace only. It is
**rejected** on tenant-admin routes (list/create/delete workspaces, org
secrets, org import, templates import, bundles) when `ADMIN_TOKEN` is set.
- **Header:** `Authorization: Bearer <workspace-token>`.
### 6. `ADMIN_TOKEN` (tenant)
- **Service:** Tenant.
- **What it is:** the per-tenant break-glass bootstrap credential set as an
environment variable on the workspace server. Required in production.
- **How to obtain:** configured at deploy time. See
[ADMIN_TOKEN — Production Requirement](/docs/self-hosting/admin-token).
- **Authorizes:** the full tenant surface (same reach as an Org API Key). Use
it to mint the first Org API Key, then prefer scoped Org API Keys for
day-to-day work.
- **Header:** `Authorization: Bearer <ADMIN_TOKEN>`.
## Credential → route tier matrix
Read this as: *for a given route surface (rows), which credentials (columns)
are accepted.* `✓` = accepted; `✗` = rejected (401/403); `—` = not applicable
to that service; `public` = no auth required.
| Surface | WorkOS session | CP admin bearer | Provision-secret | Org API Key (tenant) | Per-workspace token | `ADMIN_TOKEN` (tenant) |
|---|---|---|---|---|---|---|
| **CP** `/api/v1/orgs/*` — create, delete, export, members, billing | ✓ (+ownership) | ✗ | ✗ | ✗ (401) | — | — |
| **CP** `/api/v1/orgs/:slug/instance` — routing lookup | public | public | public | public | — | — |
| **CP** `/api/v1/admin/*` (alias `/cp/admin/*`) — fleet, tenant teardown, ws-env, pins | ✗ (403) | ✓ | ✗ | ✗ | — | — |
| **CP** `/api/v1/workspaces/provision` \| `:id` (deprovision) | ✗ | ✗ | ✓ (deprovision +`X-Molecule-Admin-Token`) | ✗ | — | — |
| **Tenant** `/workspaces/:id/*` — run, secrets, config, restart | via CP-session | — | — | ✓ (any ws in org) | ✓ (bound to `:id`) | ✓ |
| **Tenant** admin — `/workspaces` list/create/delete, `/settings/secrets`, `/org/import`, `/org/tokens`, `/templates/import`, `/bundles` | via CP-session | — | — | ✓ | ✗ (rejected when `ADMIN_TOKEN` set) | ✓ |
**Notes:**
- All bearer-token gates use **constant-time** comparison.
- Tenant gates fail-open **only** on a fresh self-host / dev boot — never on
hosted SaaS.
- `GET /api/v1/orgs/:slug/instance` is genuinely public — it is a routing
lookup, not an authenticated read. A `200` from it does not imply your key is
valid.
- An Org API Key can mint/revoke more Org API Keys via `/org/tokens`; revoke
with `DELETE /org/tokens/:id`.
- There is no scope-down below full-admin yet (planned — see
[Scoped roles](/docs/guides/org-api-keys#scoped-roles--coming-soon)).
## Picking the right credential
- **Headless integration scoped to one org** → Org API Key. This is the
default. ([Getting started](/docs/platform-management-api/getting-started).)
- **An agent that should only touch its own workspace** → per-workspace token.
- **Per-workspace billing-mode and budget automation** → Org API Key (these are
**tenant** routes — `/admin/workspaces/:id/llm-billing-mode` and
`/workspaces/:id/budget` — *not* CP-session). See the
[reference](/docs/platform-management-api/reference).
- **Workspace provisioning / deprovisioning** → provision shared-secret tier
(credential #3), not CP-session.
- **Org create/delete, member management, and the billing portal/subscription**
→ CP session tier (the Org API Key cannot reach these). Today this means
driving the dashboard's session-authed `/cp/*` proxy.
- **Platform-operator fleet work** → CP admin bearer. Operators only.
@@ -0,0 +1,139 @@
---
title: Getting Started (Org API Key)
description: The most common developer entry point to the Molecule Management API — mint an Org API Key, call the tenant host, and understand the tenant-root security caveat.
---
# Getting Started with an Org API Key
The **Org API Key** is the most common developer entry point to Molecule's
management surface. It is a tenant credential that grants full admin over your
own organization — workspaces, secrets, templates, bundles, and org tokens —
through your org's tenant host. This page gets you from zero to your first
authenticated call.
## Prerequisites
- An organization (slug, e.g. `acme`). Its tenant host is
`acme.moleculesai.app`.
- One bootstrap credential to mint the first key — either a signed-in dashboard
session, or the tenant `ADMIN_TOKEN`
([what that is](/docs/self-hosting/admin-token)).
## Step 1 — Mint an Org API Key
### Dashboard
**Settings → Org API Keys → Mint new key**, name it (e.g. `ci-bot`), and copy
the plaintext token — it is shown **once only**.
### HTTP
```bash
curl -X POST https://acme.moleculesai.app/org/tokens \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "X-Molecule-Org-Id: $ORG_ID" \
-H "Content-Type: application/json" \
-d '{"name": "ci-bot"}'
```
```json
{
"id": "tok_01HZX3B7N8PQ9K4M5R6T",
"name": "ci-bot",
"prefix": "mola_k7x9p2q4",
"auth_token": "mola_k7x9p2q4r8s1t3u5v6w0x2y3z",
"created_by": "admin-token",
"created_at": "2026-06-01T00:00:00Z"
}
```
**Save the `auth_token` value immediately** — the plaintext is shown **once**
and is never returned again. Store it as `MOLECULE_ORG_TOKEN`. (The `prefix` is
a non-secret identifier you can use to recognize the key later; subsequent list
calls return only `id`/`prefix`/metadata, never `auth_token`.)
## Step 2 — Find your tenant host (optional)
The org's routing host is a **public** CP lookup — no auth required:
```bash
curl https://api.moleculesai.app/api/v1/orgs/acme/instance
```
The response gives the tenant hostname you address for every tenant call.
## Step 3 — Make your first authenticated call
Every tenant call needs **two** headers: the bearer key and the org-id routing
header.
```bash
curl https://acme.moleculesai.app/workspaces \
-H "Authorization: Bearer $MOLECULE_ORG_TOKEN" \
-H "X-Molecule-Org-Id: $ORG_ID"
```
That lists your org's workspaces. From here, see the
[task guides](/docs/platform-management-api/tasks) for provisioning, secrets,
templates, and billing.
## Step 4 — Use it from the CLI or an MCP client
- **CLI:** the `molecule` CLI authenticates with `MOLECULE_API_KEY`
(your Org API Key). See [task guides](/docs/platform-management-api/tasks) for
per-task verbs.
<Callout type="warn">
The current `molecule` CLI's `runHTTP` path does **not** attach an
`Authorization` header, so its `workspace create`/`delete` verbs will `401`
against a hardened tenant. Fixing this (attach `Authorization: Bearer
$MOLECULE_API_KEY`) is the first item on the CLI roadmap — **verify against
the CLI source** before relying on a given verb.
</Callout>
- **MCP:** point an MCP client at your org by setting `MOLECULE_API_KEY` plus
the org headers. See [MCP Server Setup](/docs/guides/mcp-server-setup). Note
that today's MCP server is single-tenant **workspace-ops**; org-lifecycle,
cross-org, member, and billing tools are not part of it.
## What an Org API Key can and cannot do
**Can** (full tenant-admin over its own org):
- Create, delete, inspect, restart/pause/resume all workspaces
- Set workspace and org-wide secrets
- Import/export org definitions and bundles; import templates
- Manage the plugin allowlist
- Mint and revoke other Org API Keys
- Approve/reject pending workspace requests
**Cannot** (all reject it):
- Anything on the control plane — org create/delete, members, billing,
provisioning, fleet ops (`/api/v1/admin/*`, `/api/v1/orgs/*`)
- Cross into any other organization
## Security: tenant root
<Callout type="warn">
**An Org API Key is full tenant-admin and self-minting.** Because it can mint
and revoke more Org API Keys via `/org/tokens`, anything that holds one holds
**tenant root** for that org. There is **no scope-down below full-admin
today** — a "read-only" or "single-workspace" Org API Key does not exist yet.
</Callout>
Practical consequences:
- **An MCP server or CI job holding an Org API Key holds tenant root.** Scope
the blast radius accordingly — dedicated key per integration, least number of
holders, rotate on suspicion.
- **Prefer per-workspace tokens** when an agent only needs its own workspace —
they are bound to a single `:id` and cannot reach the admin surface. See
[Token Management API](/docs/guides/token-management).
- **Keep `ADMIN_TOKEN` as break-glass**, not as a day-to-day credential; mint
named Org API Keys instead so usage is attributable and revocable.
- **Revoke instantly** with `DELETE /org/tokens/:id` — revocation takes effect
on the next request, not after a background sweep.
Per-role / per-workspace scoping is planned to ship alongside a dedicated
management MCP. Until then, treat every Org API Key as a tenant-root secret.
@@ -0,0 +1,91 @@
---
title: Platform Management API
description: Manage Molecule organizations, workspaces, secrets, templates, and API keys over HTTP. The two-service architecture, the credential model, and task-oriented guides — with CLI and MCP equivalents.
---
# Platform Management API
This is the developer-facing guide to **managing a Molecule deployment over
HTTP** — provisioning workspaces, setting secrets, minting API keys, creating
organizations from templates, and configuring billing. It covers the auth
model, a task-oriented cookbook, and the machine-readable contract.
<Callout type="info">
This guide is the prose layer. The **machine-readable contract** is the
OpenAPI spec at
[`workspace-server/docs/openapi/management.yaml`](/docs/platform-management-api/reference#machine-readable-contract-openapi)
in `molecule-core` — endpoint shapes (paths, request bodies, response schemas)
derive from that file, not from this page. When this guide and the spec
disagree, the spec wins. Anything this guide marks **"verify against handler"**
is a known-uncertain detail to confirm against the spec or the route handler
before you depend on it.
</Callout>
## The one structural fact: two services, two auth stacks
Molecule is **not one API**. It is two services with two separate auth stacks,
and the single most common integration mistake is presenting a credential to
the wrong host.
### Control plane (CP)
- **Host:** `api.moleculesai.app`
- **Route prefixes:** `/api/v1/*` (stable, versioned — build against this) and
`/cp/*` (the older, identical surface; sunset-headed)
- **Owns:** organizations, members, billing, provisioning, fleet operations —
everything that exists *above* a single org.
- **Auth tiers:** WorkOS **session cookie**, CP **admin bearer**
(`CP_ADMIN_API_TOKEN`), **provision shared-secret**, **tenant-admin-token**.
### Tenant platform (per-org workspace server)
- **Host:** `<org-slug>.moleculesai.app` (one EC2 per org — e.g.
`agents-team.moleculesai.app`)
- **Owns:** workspaces, agents, secrets, templates, org tokens, bundles,
channels — everything *inside* one org.
- **Auth tiers:** **Org API Key** (`org_api_tokens`), **per-workspace token**,
`ADMIN_TOKEN`, and verified CP-session cookie — all behind `TenantGuard`
(which matches the `X-Molecule-Org-Id` routing header to the host).
### When to call which host
| You want to… | Call | Credential |
|---|---|---|
| Create / delete an org, manage members, billing | **CP** `api.moleculesai.app` | WorkOS session (ownership) |
| Fleet ops, tenant teardown, workspace env force-set, image pins | **CP** `/api/v1/admin/*` (`/cp/admin/*` is the older identical alias) | CP admin bearer |
| Provision / deprovision a workspace EC2-side | **CP** `/api/v1/workspaces/*` | provision-secret (+ `X-Molecule-Admin-Token` to deprovision) |
| List / create / restart workspaces, set secrets, mint org keys, import templates | **Tenant** `<slug>.moleculesai.app` | Org API Key (most common) |
| Look up an org's routing host (public) | **CP** `GET /api/v1/orgs/:slug/instance` | none (public) |
<Callout type="warn">
The **Org API Key** — the credential you create under dashboard **Settings →
Org API Keys** — is a **tenant** credential, not a CP one. It authorizes the
*entire tenant-admin surface of its own org* and **nothing** on the CP. Org
create/delete, members, billing, and provisioning all reject it (401/403). See
[Auth model](/docs/platform-management-api/auth-model).
</Callout>
## Where to go next
- **[Getting started](/docs/platform-management-api/getting-started)** — the
Org API Key path, the most common developer entry point. Start here.
- **[Auth model](/docs/platform-management-api/auth-model)** — every credential
type, how to obtain each, and the full credential → route tier matrix.
- **[Task guides](/docs/platform-management-api/tasks)** — provision a
workspace, set a secret, mint/revoke an Org API Key, create an org from a
template, set billing-mode and budget. Each with the exact request plus CLI
and MCP equivalents.
- **[Reference & OpenAPI contract](/docs/platform-management-api/reference)** —
the machine-readable spec and the per-surface endpoint summary.
## Related existing docs
This guide ties together several existing references; consult them for depth:
- [Org-Scoped API Keys](/docs/guides/org-api-keys) — mint/audit/revoke walkthrough.
- [Token Management API](/docs/guides/token-management) — per-workspace bearer tokens.
- [ADMIN_TOKEN — Production Requirement](/docs/self-hosting/admin-token) — the break-glass tenant credential.
- [Org Templates](/docs/org-template) — define a whole org in one YAML file.
- [Platform API (Go Backend)](/docs/api-protocol/platform-api) — tenant route tables.
- [API Reference](/docs/api-reference) — the full endpoint listing.
- [MCP Server Setup](/docs/guides/mcp-server-setup) — connect an MCP client.
@@ -0,0 +1,10 @@
{
"title": "Platform Management API",
"pages": [
"index",
"getting-started",
"auth-model",
"tasks",
"reference"
]
}
@@ -0,0 +1,107 @@
---
title: Reference & OpenAPI Contract
description: The machine-readable OpenAPI contract for the Molecule Management API, and a per-surface endpoint summary that derives from it.
---
# Reference & OpenAPI Contract
This guide's prose is the *human* layer. The **contract** — exact paths,
request bodies, response schemas, status codes — is the OpenAPI spec. This page
points you at it and gives a navigational summary by surface. It does **not**
re-author endpoint definitions, to avoid a second source of truth.
## Machine-readable contract (OpenAPI)
<Callout type="info">
The Management API contract is authored as an OpenAPI 3 document at
**`workspace-server/docs/openapi/management.yaml`** in the `molecule-core`
repository (branch `feat/openapi-management-spec`, in review as of 2026-06).
This document is the **single source of truth** for endpoint shapes. The prose
guides in this section derive from it; when they disagree, the spec wins.
</Callout>
The pre-existing swaggo-generated `workspace-server/docs/openapi/swagger.yaml`
is a `/schedules`-only **stub** and is **not** the management contract — do not
generate clients from it. Use `management.yaml` once it lands.
When the spec is published to the docs site, this page will embed the rendered
schema. Until then, read the YAML directly from the source repo.
## Endpoint summary by surface
The tables below are a **navigational index**, not the contract. Auth tiers are
per the [auth model](/docs/platform-management-api/auth-model). For request and
response shapes, consult `management.yaml`.
### Control plane — `api.moleculesai.app`
Build against the stable `/api/v1/*` prefix; `/cp/*` is identical but
sunset-headed.
| Method · Path | Purpose | Tier |
|---|---|---|
| `/auth/{signup,login,callback,signout,me,...}` | AuthKit session lifecycle | — |
| `POST /api/v1/orgs` | Create org (`412`/`402`/`409`) | WorkOS session |
| `GET /api/v1/orgs` · `GET/DELETE /api/v1/orgs/:slug` | List / get / delete (owner GDPR purge, `204`) | WorkOS session (+ownership) |
| `GET /api/v1/orgs/:slug/{export,provision-status}` | Export, provision status | WorkOS session |
| `GET /api/v1/orgs/:slug/instance` | Routing lookup | **public** |
| `…/orgs/:slug/members[...]`, invitations | Member management | WorkOS session |
| `/billing/{invoices,checkout,portal,topup,auto-credits}` | Billing | WorkOS session |
| `POST /webhooks/stripe` | Stripe webhook | signature |
| `GET /templates[/:slug]` | List templates | WorkOS session |
| `POST/DELETE /api/v1/admin/templates[/:slug]` | Manage templates | CP admin bearer |
| `GET/POST /api/v1/admin/orgs` (`?dry_run=true`) | Admin org ops | CP admin bearer |
| `GET /api/v1/admin/orgs/:slug/admin-token` | Read tenant-admin-token | CP admin bearer |
| `GET /api/v1/admin/orgs/:slug/workspaces` | List org workspaces | CP admin bearer |
| `DELETE /api/v1/admin/tenants/:slug` (body `{"confirm":"<slug>"}`) | Tenant teardown | CP admin bearer |
| `/api/v1/admin/tenants/:slug/{redeploy,reboot,diagnostics,console-output,boot-events,scrub-artifacts}` | Tenant fleet ops | CP admin bearer |
| `POST /api/v1/admin/tenants/redeploy-fleet` | Fleet rollout | CP admin bearer |
| `POST /api/v1/admin/workspaces/:id/env` | Force-set workspace env (SSM + restart) | CP admin bearer |
| `/api/v1/admin/tenants/:slug/migrate-data-volume` | Data-volume migration | CP admin bearer |
| `/api/v1/admin/{thin-ami,runtime-image}/{promote,list,rollback}` | Image/AMI pins | CP admin bearer |
| `POST /api/v1/workspaces/provision` (`422 RUNTIME_PIN_MISSING`) | Provision workspace | provision-secret |
| `DELETE /api/v1/workspaces/:id?prune=` | Deprovision | provision-secret + `X-Molecule-Admin-Token` |
| `GET /api/v1/workspaces/:id/status?instance_id=` | Provision status | provision-secret |
### Tenant workspace server — `<org-slug>.moleculesai.app`
| Method · Path | Purpose | Tier |
|---|---|---|
| `GET/POST/DELETE /workspaces[/:id]` | Workspace lifecycle | AdminAuth (Org API Key / `ADMIN_TOKEN`) |
| `PATCH /workspaces/:id` · `/restart\|/pause\|/resume\|/hibernate` | Update / lifecycle | WorkspaceAuth |
| `GET/PUT /admin/workspaces/:id/llm-billing-mode` `{mode}` | Read/set billing-mode (`platform_managed\|byok\|disabled`; `null` clears) | AdminAuth (Org API Key) |
| `GET/PATCH /workspaces/:id/budget` | Read/set budget (`budget_limits` period map) | AdminAuth (Org API Key) |
| `POST/PUT /workspaces/:id/secrets` `{key,value}` | Set workspace secret (auto-restart) | WorkspaceAuth |
| `POST /settings/secrets` | Set org-wide secret | AdminAuth |
| `POST /org/import` · `GET /org/templates` | Create workspaces from org template · list | AdminAuth |
| `GET/POST/DELETE /org/tokens[/:id]` | Mint / list / revoke Org API Keys | AdminAuth |
| `GET/PUT /orgs/:id/plugins/allowlist` | Plugin allowlist | AdminAuth |
| `GET /templates` · `POST /templates/import` | Templates | AdminAuth |
| `GET /bundles/export/:id` · `POST /bundles/import` | Bundles | AdminAuth |
| `GET/POST /workspaces/:id/tokens` | Per-workspace tokens (self-service) | WorkspaceAuth |
| `POST /admin/workspaces/:id/tokens` | Mint a per-workspace token (admin tier; used by the management MCP/CLI) | AdminAuth (Org API Key / `ADMIN_TOKEN`) |
| a2a, delegations, registry, activity, schedules, memory, approvals, traces, channels, files, mcp-bridge | Agent/runtime surface | per route |
For deeper tenant route tables see
[Platform API (Go Backend)](/docs/api-protocol/platform-api) and the
[API Reference](/docs/api-reference).
## Tooling that consumes this contract
- **CLI** — the `molecule` CLI (Go/cobra). Today it is primarily a
runtime-bridge; management verbs are being extended and its `runHTTP` path
does not yet attach `Authorization` (verify against source). See per-task
CLI lines in the [task guides](/docs/platform-management-api/tasks).
- **MCP** — [MCP Server Setup](/docs/guides/mcp-server-setup). Today's MCP
server is single-tenant **workspace-ops**; a dedicated org-key-authed
**management MCP** (org/secret/template/token tools) is planned and will be
generated from this same OpenAPI contract.
- **Dashboard** — the canonical management surface (AuthKit session +
`X-Molecule-Org-Slug`), org ops via the `/cp/*` proxy, tenant ops direct.
<Callout type="warn">
Generate clients and MCP tools from `management.yaml`, **not** from the
`/schedules`-only swaggo stub. The MCP, CLI, and these docs all derive from the
one OpenAPI contract — keeping them downstream of a single SSOT is what prevents
drift.
</Callout>
@@ -0,0 +1,300 @@
---
title: Task Guides
description: Cookbook for the Molecule Management API — provision a workspace, set a secret, mint/revoke an Org API Key, create an org from a template, and set billing-mode/budget. Each with the exact HTTP request plus CLI and MCP equivalents.
---
# Task Guides
A task-oriented cookbook for the Management API. Each task gives the **exact
HTTP request** (host, method, path, headers, body) plus the **CLI** and **MCP**
equivalents where they exist.
Conventions used below:
- `$ORG_SLUG` / `$ORG_ID` — your org's slug and id.
- `$TENANT` — your tenant host, `$ORG_SLUG.moleculesai.app`.
- `$MOLECULE_ORG_TOKEN` — an [Org API Key](/docs/platform-management-api/getting-started).
- `$CP_ADMIN_TOKEN` — the CP admin bearer (operators only).
<Callout type="info">
Request bodies and response schemas below are the prose rendering of the
[OpenAPI contract](/docs/platform-management-api/reference). Where a header name
or field is not yet pinned in the synthesis, it is marked **"verify against
handler"** — confirm against the spec or the route handler before depending on
it.
</Callout>
---
## Provision a workspace
There are **two** ways to create a workspace, on two different hosts:
### A. Tenant-side create (the common path)
Creates and provisions a workspace within your org. Org API Key works.
```http
POST https://$TENANT/workspaces
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
Content-Type: application/json
{
"name": "researcher",
"role": "Research agent",
"model": "claude-sonnet-4",
"runtime": "claude-code"
}
```
Field constraints (enforced server-side): `name` ≤ 255 chars, `role` ≤ 1000,
`model`/`runtime` ≤ 100; `name` and `role` reject newlines and YAML-special
chars (`{}[]|>*&!`). See
[Platform API breaking changes](/docs/api-protocol/platform-api#breaking-changes).
- **CLI:** `molecule workspace create --name researcher --role "Research agent" --model claude-sonnet-4 --runtime claude-code`
- **MCP:** `provision_workspace` (planned management MCP) — today, workspace
create is available in the single-tenant workspace-ops MCP.
### B. Control-plane provision (EC2-side)
The low-level provisioning entrypoint, gated by the provision shared-secret.
Build against the stable `/api/v1/workspaces/*` surface (the `/cp/workspaces/*`
prefix is the older, identical alias). Returns `422 RUNTIME_PIN_MISSING` if no
runtime image is pinned. Normally driven by the platform server-to-server, not
by integrations.
```http
POST https://api.moleculesai.app/api/v1/workspaces/provision
Authorization: Bearer <PROVISION_SHARED_SECRET>
Content-Type: application/json
{ ... }
```
**Deprovision** additionally requires the per-tenant admin token in the
**`X-Molecule-Admin-Token`** header (so a leaked shared secret can't terminate
other tenants' workspaces — controlplane #118):
```http
DELETE https://api.moleculesai.app/api/v1/workspaces/:id?prune=<bool>
Authorization: Bearer <PROVISION_SHARED_SECRET>
X-Molecule-Admin-Token: <per-tenant admin token>
```
- **Status:** `GET https://api.moleculesai.app/api/v1/workspaces/:id/status?instance_id=<id>`
---
## Set a workspace or org secret
Workspace **environment variables *are* secrets** — there is no separate `/env`
route on the tenant. Setting a secret **auto-restarts** the workspace.
### Per-workspace secret
```http
POST https://$TENANT/workspaces/:id/secrets
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
Content-Type: application/json
{ "key": "MY_API_KEY", "value": "..." }
```
(`PUT` is also accepted for upsert.) The value is encrypted AES-256-GCM into
`workspace_secrets`, emits a `secret.set` audit event, and the workspace
restarts automatically.
### Org-wide secret
```http
POST https://$TENANT/settings/secrets
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
Content-Type: application/json
{ "key": "...", "value": "..." }
```
<Callout type="warn">
**Platform-managed billing strips vendor-LLM keys.** Under platform-managed
billing, keys like `ANTHROPIC_API_KEY` and `CODEX_AUTH_JSON` are stripped on
set unless the workspace's billing-mode is flipped to `byok`
([see below](#set-billing-mode-or-budget)). Generic `GIT_HTTP_*` secrets are
never stripped.
</Callout>
- **CLI:** `molecule secret ws set --workspace <id> MY_API_KEY=...`
/ `molecule secret org set KEY=...`
- **MCP:** `set_workspace_secret` / `set_org_secret` (planned management MCP).
---
## Mint and revoke an Org API Key
Minting and revoking happen on the tenant host (`/org/tokens`). See the full
[Org-Scoped API Keys](/docs/guides/org-api-keys) walkthrough for audit fields.
### Mint
```http
POST https://$TENANT/org/tokens
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
Content-Type: application/json
{ "name": "ci-bot" }
```
Returns the plaintext `auth_token` (alongside `id` and `prefix`) **once** — it
is never returned again. An existing Org API Key, the tenant `ADMIN_TOKEN`, or a
CP session can mint.
### List
```http
GET https://$TENANT/org/tokens
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
```
Returns metadata only — the plaintext is never returned after creation.
### Revoke
```http
DELETE https://$TENANT/org/tokens/:id
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
```
Revocation is instantaneous — the next request with the revoked key fails.
- **CLI:** `molecule org token create --name ci-bot`
/ `molecule org token list`
/ `molecule org token revoke <id>`
- **MCP:** `mint_org_token` / `list_org_tokens` / `revoke_org_token` (planned
management MCP).
<Callout type="warn">
Because an Org API Key can mint **and revoke** Org API Keys, any holder is
tenant root. See the
[security note](/docs/platform-management-api/getting-started#security-tenant-root).
</Callout>
---
## Create an org from a template
Two distinct operations live under "templates": **creating workspaces from an
org template inside an existing org** (tenant `/org/import`), and **creating a
brand-new org** (CP `/api/v1/orgs`, session-tier).
### Populate an existing org from an org template
Imports a YAML org template — provisions every workspace, wires parent/child
relationships, seeds schedules, installs plugins. See
[Org Templates](/docs/org-template).
```http
POST https://$TENANT/org/import
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
Content-Type: application/json
{ ...org template YAML/JSON... } # verify body shape against handler / OpenAPI
```
List the available org templates with `GET https://$TENANT/org/templates`.
- **CLI:** `molecule org create --template <name>`
- **MCP:** `create_org_from_template` → `POST /org/import` (planned).
### Create a brand-new org (CP, session-tier)
Creating the organization *itself* is a control-plane, session-authed
operation — **an Org API Key cannot do this.**
```http
POST https://api.moleculesai.app/api/v1/orgs
<WorkOS session cookie> + X-Molecule-Org-Slug
Content-Type: application/json
{ ...org create body... }
```
Errors: `412` (no ToS accepted), `402` (quota), `409` (slug taken). A dry-run
exists for the admin variant only: `POST /api/v1/admin/orgs?dry_run=true`.
---
## Set billing-mode or budget
### LLM billing-mode
Billing-mode governs whether vendor-LLM secrets are honored
([see secret-stripping above](#set-a-workspace-or-org-secret)). It is a
**tenant** route, keyed by **workspace id** and authorized by an **Org API Key**
(plus the `X-Molecule-Org-Id` routing header) — *not* a control-plane operation:
```http
GET https://$TENANT/admin/workspaces/:id/llm-billing-mode
PUT https://$TENANT/admin/workspaces/:id/llm-billing-mode
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
Content-Type: application/json
{ "mode": "platform_managed" } # or "byok" or "disabled"
```
The `mode` field enum is **`platform_managed`**, **`byok`**, or **`disabled`**.
`{"mode":null}` **clears** the per-workspace override (falling back to the org /
default mode); an empty body `{}` is a **400** — the caller must be explicit.
- **CLI:** `molecule workspace billing-mode <mode>` (verify against CLI source).
- **MCP:** `set_llm_billing_mode` (planned management MCP).
### Workspace budget
The per-workspace LLM budget cap is read and written on the **tenant** host,
keyed by workspace id and authorized by an **Org API Key** (`PATCH` is
tenant-admin):
```http
GET https://$TENANT/workspaces/:id/budget
PATCH https://$TENANT/workspaces/:id/budget
Authorization: Bearer $MOLECULE_ORG_TOKEN
X-Molecule-Org-Id: $ORG_ID
Content-Type: application/json
{ "budget_limits": { "hourly": 100, "daily": null, "weekly": 500, "monthly": 2000 } }
```
The canonical body is the multi-period **`budget_limits`** map (per-period USD
cents; `null` clears that period). The legacy single-monthly shape
`{ "budget_limit": 2000 }` / `{ "budget_limit": null }` is still accepted for
back-compat. Sending neither `budget_limits` nor `budget_limit` is a **400**.
- **CLI:** `molecule workspace budget` (verify against CLI source).
- **MCP:** `set_workspace_budget` (planned management MCP).
---
## Other common tasks (quick reference)
| Task | Host | Method · Path | Tier |
|---|---|---|---|
| Restart / pause / resume a workspace | Tenant | `POST /workspaces/:id/{restart\|pause\|resume\|hibernate}` | Org API Key / ws-token |
| List workspaces | Tenant | `GET /workspaces` | Org API Key |
| List org templates | Tenant | `GET /org/templates` | Org API Key |
| Import a template | Tenant | `POST /templates/import` | Org API Key |
| Export / import a bundle | Tenant | `GET /bundles/export/:id` · `POST /bundles/import` | Org API Key |
| Get / set plugin allowlist | Tenant | `GET/PUT /orgs/:id/plugins/allowlist` | Org API Key |
| Delete an org (GDPR purge) | CP | `DELETE /api/v1/orgs/:slug` | WorkOS session (owner) |
| Export an org | CP | `GET /api/v1/orgs/:slug/export` | WorkOS session |
| Provision status | CP | `GET /api/v1/orgs/:slug/provision-status` | WorkOS session |
For the authoritative per-endpoint contract, see
[Reference & OpenAPI](/docs/platform-management-api/reference).