Skip to content

Workspaces

A workspace is the top-level container that owns projects, members, work entries, and agent activity. Every resource is scoped to a workspace, and every query is checked against the caller’s membership. A workspace has an owner (set at creation) and any number of admins and members — see Members.

Workspaces have no timezone; timezone is a per-user concept. See Dates and time.

Field Type Description
id string Unique identifier.
slug string URL-safe short name, unique across the instance.
name string Display name (1–100 chars).
accentColor string Accent theme: neutral, red, orange, amber, green, teal, blue, violet, or pink.
logoUrl string | null URL of the workspace logo, or null when none is set.
settings object Free-form workspace settings map.
createdAt string ISO 8601 creation instant.
archivedAt string | null ISO 8601 instant the workspace was archived, or null when active.

GET /api/v1/workspaces scope: read

Returns the workspaces the caller belongs to. Instance admins receive every workspace on the instance; for a workspace they are not a member of, role is null. Each item is a workspace object with the caller’s role (owner, admin, member, or null) added.

curl "https://<your-instance>/api/v1/workspaces" \
  -H "Authorization: Bearer spantail_pat_yourtoken"

POST /api/v1/workspaces scope: admin

Creates a workspace owned by the caller. Instance admin only. The slug must be unique across the instance; a duplicate returns 409 conflict.

Request body

Field Type Required Description
slug string yes URL-safe short name, unique across the instance.
name string yes Display name (1–100 chars).
curl -X POST "https://<your-instance>/api/v1/workspaces" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{ "slug": "demo", "name": "Demo" }'

Returns 201 Created. The caller becomes the workspace owner.

GET /api/v1/workspaces/:id scope: read

Returns a single workspace. Requires membership; a workspace the caller cannot see returns 404.

PATCH /api/v1/workspaces/:id scope: admin

Updates workspace fields. Workspace admins only. All body fields are optional; send just what changes. Changing slug to one already taken returns 409 conflict.

Request body

Field Type Required Description
slug string no URL-safe short name, unique across the instance.
name string no Display name (1–100 chars).
accentColor string no Accent theme (see the workspace object).
archived boolean no true archives the workspace, false restores it (sets/clears archivedAt).
curl -X PATCH "https://<your-instance>/api/v1/workspaces/wrk_demo" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Demo workspace", "accentColor": "teal" }'

Returns the updated workspace object.

DELETE /api/v1/workspaces/:id scope: admin

Permanently deletes a workspace. Workspace owner only (instance admins may also delete any workspace); a workspace admin who is not the owner gets 403. An archived workspace can be deleted without restoring it first.

curl -X DELETE "https://<your-instance>/api/v1/workspaces/wrk_demo" \
  -H "Authorization: Bearer spantail_pat_yourtoken"

Returns 204 No Content.

GET /api/v1/workspaces/:id/logo scope: read

Returns the raw logo image bytes (not JSON), served through the Worker so membership is checked on every load. Requires membership. Returns 404 when no logo is set. The response carries an ETag; a matching If-None-Match yields 304 Not Modified.

PUT /api/v1/workspaces/:id/logo scope: admin

Uploads the logo. Workspace admins only. The request body is the raw image bytes, with the Content-Type set to the image type.

curl -X PUT "https://<your-instance>/api/v1/workspaces/wrk_demo/logo" \
  -H "Authorization: Bearer spantail_pat_yourtoken" \
  -H "Content-Type: image/png" \
  --data-binary @logo.png

Returns the updated workspace object, with logoUrl pointing at the new logo.

DELETE /api/v1/workspaces/:id/logo scope: admin

Removes the logo. Workspace admins only. Returns the updated workspace object with logoUrl set to null.