docs: Platform Management API developer guide #57
@@ -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).
|
||||
Reference in New Issue
Block a user