On this page

Workspaces group resources inside an organization. In a white-label platform, a workspace usually represents one downstream customer or client, such as Dr. Smith Clinic inside the ClinicIQ organization. Projects live inside workspaces, and sandboxes, computers, deployments, databases, storage buckets, volumes, functions, jobs, and domains belong to projects.

Base path: /api/v1/workspaces


Quick Start

import { Miosa } from '@miosa/sdk';

const client = new Miosa(); // reads MIOSA_API_KEY

// Create a workspace for a downstream customer
const ws = await client.workspaces.create({
  name: 'Dr. Smith Clinic',
  slug: 'dr-smith-clinic',
  externalWorkspaceId: 'clinic_123',
});

// Create a computer inside a project in that workspace
const computer = await client.computers.create({
  name: 'clinic-builder',
  templateType: 'miosa-desktop',
  workspaceId: ws.id,
  projectSlug: 'lead-magnet',
  projectName: 'Lead Magnet',
});

// List computers in the workspace
const { data } = await client.workspaces.listComputers(ws.id);
# curl equivalent
curl -X POST https://api.miosa.ai/api/v1/workspaces 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"name": "Dr. Smith Clinic", "slug": "dr-smith-clinic", "external_workspace_id": "clinic_123"}'

Endpoints

MethodPathDescription
GET/workspacesList workspaces for the tenant
POST/workspacesCreate a workspace
GET/workspaces/{id}Get a workspace
PATCH/workspaces/{id}Update a workspace
PUT/workspaces/{id}/settingsUpdate workspace-level resource limits
GET/workspaces/{id}/preview-domainRead the workspace preview domain
PUT/workspaces/{id}/preview-domainSet the workspace preview domain
DELETE/workspaces/{id}/preview-domainClear the workspace preview domain
GET/workspaces/{id}/preview-domain/verifyCheck DNS readiness
DELETE/workspaces/{id}Delete a workspace
GET/workspaces/{id}/computersList computers in a workspace
GET/workspaces/{id}/statsComputer counts and resource totals
GET/workspaces/{id}/usageTime-series credit and compute usage
GET/workspaces/{id}/projectsList projects in a workspace

List Workspaces

GET /api/v1/workspaces

Returns all workspaces belonging to the authenticated tenant.

Response — 200 OK

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "tenant_id": "...",
      "name": "default",
      "slug": "default",
      "external_workspace_id": null,
      "description": null,
      "metadata": {},
      "is_default": true,
      "computer_count": 3,
      "created_at": "2026-04-11T00:00:00Z",
      "updated_at": "2026-04-11T00:00:00Z"
    }
  ],
  "total": 1
}
curl https://api.miosa.ai/api/v1/workspaces 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Create a Workspace

POST /api/v1/workspaces

Request Body

FieldTypeRequiredDescription
namestringYesHuman-readable name (1–120 chars)
slugstringNoURL-safe identifier. Auto-derived from name if omitted. Pattern: [a-z0-9][a-z0-9-]{0,79}
external_workspace_idstringNoYour customer/account/workspace ID. Globally unique inside this MIOSA organization.
descriptionstringNoOptional description
metadataobjectNoCaller metadata stored on the workspace.

Response — 201 Created

Full workspace object (same shape as list items above).

Errors

StatusErrorCause
422has already been takenSlug already exists in tenant
422must start with alphanumeric and contain only a-z 0-9 -Invalid slug format
curl -X POST https://api.miosa.ai/api/v1/workspaces 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{
    "name": "Dr. Smith Clinic",
    "slug": "dr-smith-clinic",
    "external_workspace_id": "clinic_123",
    "description": "Client workspace for Dr. Smith Clinic"
  }'

Get a Workspace

GET /api/v1/workspaces/{id}

Path Parameters

ParameterTypeDescription
idUUIDWorkspace ID

Response — 200 OK

Full workspace object.

Errors

StatusErrorCause
403forbiddenWorkspace belongs to a different tenant
404workspace not foundDoes not exist
curl https://api.miosa.ai/api/v1/workspaces/{id} 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Update a Workspace

PATCH /api/v1/workspaces/{id}

Update mutable workspace fields. Prefer treating the slug as stable once resources and URLs exist.

Request Body

FieldTypeDescription
namestringNew display name
slugstringNew URL-safe slug. Must remain unique inside the organization.
descriptionstringNew description (null to clear)
external_workspace_idstringYour customer/account/workspace ID
metadataobjectReplacement metadata map

Response — 200 OK

Updated workspace object.

Errors

StatusErrorCause
403forbiddenWrong tenant
404workspace not foundDoes not exist
curl -X PATCH https://api.miosa.ai/api/v1/workspaces/{id} 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"name": "production-us-east"}'

Delete a Workspace

DELETE /api/v1/workspaces/{id}

Deletes an empty workspace. Fails if the workspace contains computers or projects.

Response — 200 OK

{ "deleted": true }

Errors

StatusErrorCause
403forbiddenWrong tenant
404workspace not foundDoes not exist
409workspace has computersRemove or move resources first
curl -X DELETE https://api.miosa.ai/api/v1/workspaces/{id} 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Update Workspace Settings

PUT /api/v1/workspaces/{id}/settings

Applies resource limits and default preferences for the workspace. These limits cap what any computer inside the workspace can do. Tenant-level limits still apply as a ceiling.

Request Body

FieldTypeRequiredDescription
max_computersintegerNoMaximum number of computers allowed in this workspace. null = no workspace-level cap (tenant limit applies).
max_computer_sizestringNoMaximum size value a computer in this workspace may be created with: "small", "medium", or "large".
default_computer_sizestringNoDefault size applied when creating a computer without an explicit size.
default_auto_stop_secondsintegerNoAuto-stop idle timeout (seconds) applied to new computers by default. 0 = no auto-stop.
allowed_template_typesstring[]NoAllowlist of template names that can be used in this workspace. Empty array = all templates allowed.

Response — 200 OK

{
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "settings": {
    "max_computers": 10,
    "max_computer_size": "large",
    "default_computer_size": "small",
    "default_auto_stop_seconds": 3600,
    "allowed_template_types": []
  },
  "updated_at": "2026-05-17T10:00:00Z"
}

Workspace Preview Domain

PUT /api/v1/workspaces/{id}/preview-domain

Sets a client/workspace-level base domain for generated URLs. This overrides the organization preview domain for resources in this workspace unless a project has its own preview domain.

curl -X PUT https://api.miosa.ai/api/v1/workspaces/{id}/preview-domain 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"preview_domain":"drsmithclinic.com"}'

Response:

{
  "scope": "workspace",
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "preview_domain": "drsmithclinic.com",
  "effective_domain": "drsmithclinic.com",
  "status": "pending_dns",
  "dns_status": "pending",
  "url_examples": {
    "default_preview": "https://<slug>.drsmithclinic.com",
    "port_preview": "https://3000-<slug>.sandbox.drsmithclinic.com",
    "deployment": "https://<deployment-slug>.drsmithclinic.com"
  }
}

Required DNS records:

Record typeNameValue
CNAME*proxy.miosa.ai
CNAME*.sandboxproxy.miosa.ai

Verify:

curl https://api.miosa.ai/api/v1/workspaces/{id}/preview-domain/verify 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Clear and inherit from the organization/domain fallback:

curl -X DELETE https://api.miosa.ai/api/v1/workspaces/{id}/preview-domain 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Errors

StatusErrorCause
403forbiddenWrong tenant
404workspace not foundDoes not exist
422VALIDATION_FAILEDUnknown size value or invalid limit
curl -X PUT https://api.miosa.ai/api/v1/workspaces/{id}/settings 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{
    "max_computers": 10,
    "max_computer_size": "large",
    "default_auto_stop_seconds": 3600
  }'

List Computers in a Workspace

GET /api/v1/workspaces/{id}/computers

Response — 200 OK

{
  "data": [
    {
      "id": "...",
      "name": "runner-1",
      "status": "running",
      "size": "small",
      "template_type": "miosa-desktop",
      "created_at": "2026-04-11T00:00:00Z"
    }
  ],
  "total": 1
}
curl https://api.miosa.ai/api/v1/workspaces/{id}/computers 
  -H "Authorization: Bearer $MIOSA_API_KEY"

List Projects in a Workspace

GET /api/v1/workspaces/{id}/projects

Returns the projects owned by a workspace. Use this for client dashboards before listing the sandboxes, computers, deployments, and databases inside a project.

Response - 200 OK

{
  "data": [
    {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "tenant_id": "...",
      "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
      "external_workspace_id": "clinic_123",
      "external_project_id": "project_789",
      "name": "Lead Magnet",
      "slug": "lead-magnet",
      "description": null,
      "metadata": {},
      "created_at": "2026-05-18T10:00:00Z",
      "updated_at": "2026-05-18T10:00:00Z"
    }
  ],
  "total": 1
}
curl https://api.miosa.ai/api/v1/workspaces/{id}/projects 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Get Workspace Stats

GET /api/v1/workspaces/{id}/stats

Returns a snapshot of computer counts grouped by status and the aggregate resource footprint for the workspace.

Response — 200 OK

{
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "computers": {
    "total": 5,
    "by_status": {
      "running": 3,
      "stopped": 2,
      "provisioning": 0,
      "error": 0
    }
  },
  "resources": {
    "total_vcpus": 7,
    "total_memory_mb": 28672,
    "total_disk_gb": 160
  },
  "settings": {
    "max_computers": 10,
    "max_computer_size": "large",
    "default_auto_stop_seconds": 3600
  }
}
curl https://api.miosa.ai/api/v1/workspaces/{id}/stats 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Get Workspace Usage

GET /api/v1/workspaces/{id}/usage

Returns time-series credit consumption and compute-hour totals for the workspace over a given window. Use this for per-workspace cost attribution dashboards.

Query Parameters

ParameterTypeDescription
windowstring"24h" (default), "7d", "30d"
granularitystring"hour" (default), "day" — bucket size for the time-series data

Response — 200 OK

{
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "window": "7d",
  "granularity": "day",
  "total_credits_used": 1284,
  "total_compute_hours": 42.5,
  "series": [
    {
      "ts": "2026-05-10T00:00:00Z",
      "credits_used": 198,
      "compute_hours": 6.6
    },
    {
      "ts": "2026-05-11T00:00:00Z",
      "credits_used": 211,
      "compute_hours": 7.0
    }
  ]
}

Errors

StatusErrorCause
403forbiddenWrong tenant
404workspace not foundDoes not exist
422VALIDATION_FAILEDUnknown window or granularity value
curl "https://api.miosa.ai/api/v1/workspaces/{id}/usage?window=7d&granularity=day" 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Common Recipes

Move all computers to a new workspace

Computers do not yet support a move operation on workspace assignment via PATCH /computers/{id}. Use the POST /computers/{id}/move endpoint instead:

curl -X POST https://api.miosa.ai/api/v1/computers/{computer_id}/move 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"workspace_id": "target-workspace-id"}'

Enumerate all workspaces and their sizes

const { data: workspaces } = await client.workspaces.list();
for (const ws of workspaces) {
  console.log(`${ws.name}: ${ws.computerCount} computers`);
}

Default workspace ID lookup

If you need the default workspace ID programmatically:

const { data } = await client.workspaces.list();
const defaultWs = data.find(ws => ws.isDefault);
console.log(defaultWs.id);

Common Errors

StatusCodeCause
403forbiddenWorkspace belongs to a different tenant
404workspace not foundDoes not exist
409workspace has computersCannot delete a workspace that contains computers
422VALIDATION_FAILEDName or slug failed schema validation

See also

Was this helpful?