Skip to content

Create, list, and delete workspaces

The tenant-credential routes — what quota really reports, the password rule that refuses a workspace, and what force revokes on delete.

Updated View as Markdown

Every route here uses tenant credentials, never a workspace token.

GET /v1/workspaces

List the tenant’s workspaces. Returns 200.

{
  "workspaces": [
    { "slug": "demo", "createdAt": "2025-06-01T09:15:00.000Z", "walletCount": 12 }
  ]
}

GET /v1/quota

Report the tenant’s configured limits and current usage. Returns 200.

curl "$API_URL/quota" -H "X-Api-Key: $API_KEY" -H "X-Api-Secret: $API_SECRET"
{
  "workspaces": { "used": 3, "limit": 10 },
  "wallets": { "used": 128, "limit": 500 }
}

Two counters, both tenant-wide: workspaces you have created, and wallets across all of them. walletCount on each workspace record breaks the second one down.

This route does not report how many workspaces may be open at once. That ceiling exists — it is what session_capacity_exceeded enforces — but it is not exposed by any route.

POST /v1/workspaces

Create a workspace. Returns 201.

Request

{ "slug": "demo", "password": "a-strong-workspace-password" }
Field Type Required Notes
slug string yes Lowercase letters, digits, hyphens; starts alphanumeric; ≤63 chars. con, prn, aux and nul are reserved and refused despite fitting that rule
password string yes At least 12 characters. Shorter is rejected with 422 and weak_password

Response

{
  "workspace": {
    "slug": "demo",
    "createdAt": "2025-06-01T09:15:00.000Z",
    "walletCount": 0
  }
}

Errors

Status Code
400 invalid_body, invalid_slug
401 bad_api_key
409 workspace_exists, workspace_in_use, quota_workspaces_exceeded
422 weak_password
429 workspace_creation_rate_limited, workspace_recreation_cooldown, session_capacity_exceeded
500 storage_error — the workspace exists in the ledger but could not be opened

Creating a workspace holds an open handle for as long as it takes, so it competes for the same ceiling a token mint does: with too many workspaces already open, create answers 429 with session_capacity_exceeded. workspace_in_use is the narrower case where that exact slug is already held open — a create racing another create, or a mint, on the same name.

DELETE /v1/workspaces/{slug}

Delete a workspace and everything in it. Returns 204.

Query parameters

Parameter Values Default Meaning
force true or false false Delete even while live token leases hold the workspace

force accepts exactly those two strings. Anything else returns 400 with invalid_parameter — there is no truthy-string coercion.

Without force, deleting a workspace that is still held returns 409 with workspace_in_use. “Held” means live token leases — an expired session, or one whose last token was revoked, does not block the delete even though it still exists. A workspace caught mid-open or mid-close is refused the same way. force overrides all of it: it is read before the check runs, so it applies to every form of this refusal on delete.

Create is the exception, and only because it has no force to give: the same code answers POST /v1/workspaces when that slug is already being held, and there the only option is to retry once it settles.

Errors

Status Code
400 invalid_slug, invalid_parameter
401 bad_api_key
403 permission_denied — the storage refused the delete
404 workspace_not_found
409 workspace_in_use
500 storage_error — a ledger write during removal failed

?force=true overrides the 409, which is a live-session refusal. It does not override the 403, which comes from the storage layer and stands regardless.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close