Workspaces per Customer
Provision, address, and retire an isolated workspace for each end-customer.
Each of your customers gets their own workspace. The boundary is real: agents, credentials, runs, sessions, and usage in one workspace are invisible to every other. Provision one when a customer signs up, act on it over the API, suspend it when they leave — and when they leave for good, delete it with one call.
Provision
curl -X POST https://api.levainlabs.com/api/v1/org/workspaces \
-H "Authorization: Bearer $LEVAIN_ORG_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Tools", "external_id": "customer_42"}'The response carries the workspace id — store it against the customer in your
own database; it's the value you'll send in X-Workspace-Id from then on. The
new workspace starts empty and headless: no members, no sign-in, no agents until
you adopt one.
Provisioning requires the Enterprise plan, and an org can hold up to 500
workspaces. Send external_id (e.g. your customer id) to make the call safely
retryable: a repeat call whose external_id matches an existing workspace
returns that workspace with status 200 instead of creating another. If a
create fails or times out, don't guess — recover by calling
GET /api/v1/org/workspaces?external_id=
with the same value to find out whether the workspace exists.
A replayed create can return a workspace whose provisioning is still in flight. If that provisioning later fails, the workspace is removed — a subsequent lookup for it may then 404.
Address
Send the workspace id with an org key on any workspace-scoped endpoint:
curl https://api.levainlabs.com/api/v1/agents \
-H "Authorization: Bearer $LEVAIN_ORG_KEY" \
-H "X-Workspace-Id: $CUSTOMER_WORKSPACE_ID"The rules are strict on purpose:
- An org key with
X-Workspace-Idacts on that workspace. An unknown id, or one belonging to another org, returns404. - An org key without the header only resolves when the org has exactly one
workspace; otherwise the request is refused with
400and asks you to pick. - A workspace-scoped key naming a different workspace in
X-Workspace-Idis refused with403rather than silently ignored, so a caller never acts somewhere other than where it asked to.
List what you have with
GET /api/v1/org/workspaces
— each row carries headless (whether anyone can sign in) and lifecycle.
Knowledge base
Every workspace carries a knowledge base — shared context that agents in the
workspace read before they act. The knowledge base is provisioned on first
access: the first
GET /api/v1/wikis/current
or the first page write creates it and seeds overview.md, DESIGN.md, and
VOICE.md. In a workspace where people sign in, that first access happens when
someone opens the knowledge base. In a headless workspace it never does on its
own — so if your customer's agents should run with context, provision and seed
it during onboarding. Fetching the id below is itself a first access and
creates the knowledge base; the write that follows seeds your content into it:
WIKI_ID=$(curl -s https://api.levainlabs.com/api/v1/wikis/current \
-H "Authorization: Bearer $LEVAIN_ORG_KEY" \
-H "X-Workspace-Id: $CUSTOMER_WORKSPACE_ID" | jq -r .id)
curl -X PUT "https://api.levainlabs.com/api/v1/wikis/$WIKI_ID/pages/VOICE.md" \
-H "Authorization: Bearer $LEVAIN_ORG_KEY" \
-H "X-Workspace-Id: $CUSTOMER_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{"body": "# Voice\n\nPlain and direct. Short sentences."}'The seeded pages are writable like any other page — only deleting them is
restricted — and every write through
PUT /api/v1/wikis/{wiki_id}/pages/{page_path}
is stamped user_edited_at, which tells the maintainer agent to treat your
content as append-only rather than rewrite it. Agents only receive the
knowledge base once it exists, so write your context before the first run,
not after.
Lifecycle
A workspace is active, dormant, or suspended.
Suspend a workspace when its customer offboards:
curl -X POST https://api.levainlabs.com/api/v1/org/workspaces/$WS_ID/lifecycle \
-H "Authorization: Bearer $LEVAIN_ORG_KEY" \
-H "Content-Type: application/json" \
-d '{"state": "suspended"}'Suspended workspaces refuse new runs until you set them back to active. Data,
agents, and configuration are all kept, so re-onboarding a returning customer is
the same call in reverse. The org's primary workspace can't be suspended — it
carries the org's plan and sign-in.
Dormant is automatic: a workspace with no activity for 30 days is marked
dormant, and the next run clears it. You never set it yourself; treat it as a
signal that a customer has gone quiet.
Delete
When a customer leaves, the whole of it leaves with them — one call:
curl -X DELETE https://api.levainlabs.com/api/v1/org/workspaces/$WS_ID \
-H "Authorization: Bearer $LEVAIN_ORG_KEY"The call returns immediately and is irreversible. From that moment the
workspace no longer resolves on any endpoint — its own API keys stop working
and it disappears from GET /api/v1/org/workspaces. Everything inside is then
permanently removed:
- agents, their versions and repositories
- the knowledge base and every uploaded or crawled document
- agent memory
- integration credentials, provider keys, and workspace API keys
- sessions, runs, and their event records
- members, schedules, triggers, and notifications
Retention. Removal from live systems completes within 7 days of the call; encrypted database backups holding the data expire within 35 days after that. This is the wording to cite when a customer's GDPR erasure request reaches you: their data is deleted from live systems within 7 days and from all backups within 42 days.
What survives. Invoices, the credit ledger, and aggregate usage totals are retained for financial record-keeping. They reference the workspace by identifier and name only — none of its contents.
Deletion is for offboarding for good. If the customer might return, suspend instead: suspension keeps everything and reverses with one call; deletion keeps nothing and doesn't. The org's primary workspace can't be deleted.