Workspaces API
List, create, read, freeze, and export workspace metadata.
Base path: /v1/workspaces
See also: Workspaces
List workspaces
GET /v1/workspacesReturns every workspace you can access: workspaces you hold a direct membership on, plus all workspaces under any organization you belong to.
Permission: implicit via membership
curl -s -H "Authorization: Bearer $TOKEN" \
"https://platform.groundfloor.cloud/v1/workspaces" | jq .Query parameters
| Name | Type | Default | Description |
|---|---|---|---|
limit | integer | 100 | Max workspaces returned (1-500) |
Response 200
[
{
"id": "8ca7d2a2-…",
"account_id": "…",
"organization_id": "…",
"name": "Production",
"slug": "production",
"status": "active",
"region": "us-east-1",
"tenancy_model": "direct",
"frozen_at": null,
"deletion_requested_at": null,
"scheduled_deletion_at": null,
"created_at": "2026-05-01T12:00:00Z",
"updated_at": "2026-05-01T12:00:00Z",
"created_by": "…"
}
]| Field | Notes |
|---|---|
status | active, frozen or archived |
tenancy_model | direct, subtenant_of or partner_managed |
account_id / organization_id | Same value; both are returned |
frozen_at | Set when the workspace was frozen |
deletion_requested_at / scheduled_deletion_at | Set only while a deletion request is pending |
created_by, created_by_display_name, created_by_email | Who created the workspace, when known |
Create workspace
POST /v1/workspacesStarts setting up the workspace: its environments, data API and permissions. Returns 202 Accepted with a provisioning run ID — not the final workspace synchronously.
Permission: administer on the parent organization (and on the parent workspace when parent_workspace_id is set)
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"account_id":"<organization_uuid>","name":"Development","slug":"development","tenancy_model":"direct"}' \
"https://platform.groundfloor.cloud/v1/workspaces" | jq .Request body
| Field | Type | Required | Description |
|---|---|---|---|
account_id (or organization_id) | uuid | Yes | Parent organization. Send either name; if you send both they must be equal |
name | string | Yes | Display name, 1-255 characters |
slug | string | Yes | Lowercase letters, digits and hyphens, 1-63 characters. Not generated for you. Must not collide with another workspace's branded host (409) |
tenancy_model | string | Yes | direct, subtenant_of or partner_managed. No default |
region | string | No | Defaults to the cell's region. Must be a region available on that cell, otherwise 422 |
environments | string or array | No | "default" (default) creates dev, staging and prod; "none" creates none; or pass a list of environment names. Ignored for subtenant_of, which always gets none |
parent_workspace_id | uuid | Only for subtenant_of | Required when tenancy_model is subtenant_of; must be omitted for direct. The parent must be an active direct workspace in the same organization |
A subtenant_of workspace gets no environments, so nothing can be deployed into it. The Client Portal no longer offers it.
| settings_json | object | No | No keys are currently accepted from callers; any non-empty object is rejected with 422 |
Response 202
{
"workspace_id": "8ca7d2a2-…",
"provisioning_run_id": "…"
}Errors
| Status | When |
|---|---|
400 | subtenant_of on an organization that is not an ISV organization; parent workspace does not use the direct model |
403 | Missing administer on the organization or the parent workspace; parent belongs to a different organization |
404 | Organization or parent workspace not found |
409 | Plan workspace quota reached; organization is suspended or scheduled for deletion; parent workspace is not active; slug would collide with another workspace's host |
422 | Missing slug or tenancy_model, invalid slug, region not available, or settings_json keys set |
429 | Rate limit: 10 creates per minute |
Get workspace
GET /v1/workspaces/{workspace_id}Permission: read on workspace
List workspaces by organization
GET /v1/workspaces/by-organization/{organization_id}/v1/workspaces/by-account/{organization_id} also works. Accepts the same limit parameter (1-500).
Permission: read on organization. Callers who only hold a workspace membership under the organization see just those workspaces.
List environments
GET /v1/workspaces/{workspace_id}/environmentsReturns the workspace's environments. A workspace created with environments: "default" has dev, staging and prod; one created with "none" or a custom list has what you asked for, and environments can be added later (see Environments API).
Permission: read on workspace
Freeze a workspace
PATCH /v1/workspaces/{workspace_id}/statusFreeze a workspace. Freezing is a suspension: it sets no deletion date and nothing is erased. To delete a workspace, see Delete a workspace.
{ "status": "frozen" }Freezing is one-way. frozen is the only accepted value and there is no route to unfreeze. Restoring a workspace only lifts the freeze that a deletion request sets, and a frozen workspace can't be scheduled for deletion; contact Groundfloor support to reactivate it. Once frozen, write requests to the workspace's routes fail with 423 Locked. Reads, export and changes that only remove access, such as deleting a secret or a deployment, keep working. Don't call this to test the API on a workspace you want to keep using.
Returns the updated workspace record.
Permission: administer on workspace
| Status | When |
|---|---|
409 | The workspace is already frozen, or cannot be frozen in its current state (for example it is archived) |
422 | Any status value other than frozen |
Set the default app
PUT /v1/workspaces/{workspace_id}/default-appSets, or clears, the workspace's default app. Idempotent. The app lists return it as default_app_slug. The Shell site doesn't use it yet: it opens the app the user last opened in the workspace, otherwise the first app.
{ "app_slug": "storefront" }Send {"app_slug": null} to clear it. The slug must name a non-archived app of kind shell_federated in this workspace. Returns {"workspace_id": "…", "default_app_slug": "storefront"}.
Permission: write on workspace
| Status | When |
|---|---|
403 | Missing write |
404 | Workspace or app slug not found |
409 | The app is archived |
422 | The app is not shell_federated, or the body is invalid |
423 | The workspace is frozen |
Export workspace metadata
GET /v1/workspaces/{workspace_id}/exportStreams one JSON file (Content-Disposition: attachment) with the workspace's metadata:
| Included | Not included |
|---|---|
| The workspace record | App data, Data Vault records or database contents |
| Memberships | Files |
| Environments | Secrets |
| Provisioning runs | Deployed code or Coderunner packages |
| Audit events (up to 10,000 per list) |
This is not a backup and not a data-exit path for your application data. Use the Data Vault, Files and Databases APIs to move that data.
The response is JSON only. A legacy upload query flag is accepted and ignored.
The file leaves out internal platform details, and secret-like values in audit events are removed.
Permission: administer on the workspace: workspace Owners and Admins, and organization Owners and Admins. Everyone else gets 403. Export keeps working on a frozen workspace.
Workspace audit
GET /v1/workspaces/{workspace_id}/audit?limit=50Permission: read on workspace
Related pillar endpoints
All scoped under /v1/workspaces/{workspace_id}/:
| Pillar | Path prefix |
|---|---|
| Secrets | /secrets |
| Files | /files |
| Data Vault | /vault |
| Process Log | /logs |
| Apps | /apps |
| Coderunners | /coderunners |