Skip to content

How to create and delete workspaces

The two counters quota actually reports, the twelve-character password rule, and what force revokes when you delete a workspace in use.

Updated View as Markdown

Examples on this page use $API_URL. Set it once, with the /v1 prefix included — every route lives under it:

export API_URL=https://<your-api-host>/v1

Workspaces are administered entirely with tenant credentials. None of these routes take a workspace token.

Check your quota first

curl "$API_URL/quota" \
  -H "X-Api-Key: $API_KEY" -H "X-Api-Secret: $API_SECRET"
{
  "workspaces": { "used": 2, "limit": 10 },
  "wallets": { "used": 7, "limit": 40 }
}

That is two of the limits your operator set — how many workspaces you may hold, and how many wallets in total — with your current usage of each. Reading it before a bulk provisioning run is cheaper than discovering the ceiling halfway through. wallets.used counts across every workspace the tenant holds, and it counts the wallet each account is created with, not only the ones you derive.

It does not report how many workspaces may be held open at once. That is a separate ceiling, enforced by session_capacity_exceeded — raised on workspace create as well as on mint. No route reports the ceiling up front, but the refusal itself carries details.scope and details.limit, so the first one tells you which ceiling you met and what it is.

Create

curl -X POST "$API_URL/workspaces" \
  -H "X-Api-Key: $API_KEY" -H "X-Api-Secret: $API_SECRET" \
  -H "content-type: application/json" \
  -d '{"slug":"demo","password":"a-strong-workspace-password"}'

Returns 201 with the row you will see again in the listing:

{ "workspace": { "slug": "demo", "createdAt": "2026-08-25T09:15:00.000Z", "walletCount": 0 } }

Slugs are lowercase letters, digits, and hyphens, starting alphanumeric, up to 63 characters, and con, prn, aux and nul are reserved as directory names and refused despite fitting the rule. A malformed or reserved slug returns 400 with invalid_slug — the details.expected field says which of the two it was; a slug already in use returns 409 with workspace_exists.

The password is held to a twelve-character minimum, and it is checked first — before the slug is reserved, before the quota is consulted, and before any rate limit is charged. A password that fails the policy returns 422 with weak_password and costs you nothing else.

Creation is rate-limited per tenant (429, workspace_creation_rate_limited), and a workspace that was recently deleted cannot immediately be recreated under the same slug (429, workspace_recreation_cooldown).

List

curl "$API_URL/workspaces" \
  -H "X-Api-Key: $API_KEY" -H "X-Api-Secret: $API_SECRET"
{
  "workspaces": [
    { "slug": "demo", "createdAt": "2025-06-01T09:15:00.000Z", "walletCount": 12 }
  ]
}

Delete

curl -X DELETE "$API_URL/workspaces/demo" \
  -H "X-Api-Key: $API_KEY" -H "X-Api-Secret: $API_SECRET"

Returns 204. If the workspace currently has an open session, the call is refused with 409 and workspace_in_use rather than pulling the floor out from under an active caller.

To delete anyway, opt in explicitly:

curl -X DELETE "$API_URL/workspaces/demo?force=true" \
  -H "X-Api-Key: $API_KEY" -H "X-Api-Secret: $API_SECRET"

force accepts exactly true or false. Any other value returns 400 with invalid_parameter — there is no truthy-string coercion, so ?force=1 and ?force=yes both fail. Repeating the parameter (?force=true&force=false) fails the same way rather than one value winning.

Deleting a workspace destroys its accounts and their key material. If anything inside needs to survive, export it first.

Failures worth handling

Code Status What happened
invalid_body 400 Body is not { slug, password }. The message names the offending fields
invalid_slug 400 Slug syntax is wrong
invalid_parameter 400 force was not exactly true or false
bad_api_key 401 Tenant credentials missing or wrong
weak_password 422 Password is below the twelve-character policy
workspace_exists 409 Slug already in use
workspace_not_found 404 No such workspace for this tenant
workspace_in_use 409 Live token leases hold it, or it is mid-open or mid-close; force=true overrides either. On create the same code means the slug is already being held, and create takes no force — retry once it settles
quota_workspaces_exceeded 409 Tenant workspace limit reached
workspace_creation_rate_limited 429 Creating too quickly
workspace_recreation_cooldown 429 Slug was recently deleted

Both 429s carry details.retryAfterSec and a matching retry-after header — wait it out rather than retrying immediately.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close