Remote Workspaces API

Authenticate to the Kimchi Workspaces API and manage Remote Workspaces, workspace templates, sessions, events, and costs over HTTPS.

The Remote Workspaces API is the HTTP interface to Kimchi's remote workspace infrastructure. It lets you create and manage the cloud sandboxes behind Remote Workspaces — workspaces, the templates they are provisioned from, the sessions running inside them, and the events, usage, and costs they produce — without touching the Kimchi console.

This guide covers authentication, the available endpoints grouped by what they do, and how to call them.

Prerequisites

  • A Kimchi account with access to an organization that has Remote Workspaces enabled.
  • An API key or Service Key with permission to manage workspaces. Create one on the API Keys page in the Kimchi console (see API Keys and Service Keys).
  • Your organization ID. Every management endpoint takes it as a path parameter ({organizationId}).

Base URL

All Workspaces API endpoints are served from the same hosts as the rest of the Kimchi API, under the /ai-optimizer/v1beta prefix:

RegionBase URL
UShttps://api.cast.ai/ai-optimizer/v1beta
EUhttps://api.eu.cast.ai/ai-optimizer/v1beta
Indiahttps://api.india.cast.ai/ai-optimizer/v1beta

Use the host for the region your organization is in.

Authentication

Every request must authenticate with one of two methods:

  • X-API-Key header — send your API key or Service Key:
    curl -H 'X-API-Key: {KEY}' https://api.cast.ai/ai-optimizer/v1beta/...
  • Bearer token — send a Kimchi identity token (the JWT used by Kimchi itself):
    curl -H 'Authorization: Bearer {TOKEN}' https://api.cast.ai/ai-optimizer/v1beta/...
📘

Workspace cost data follows the same visibility rules as the workspace list: members see their own workspaces plus org-wide shared ones, and organization owners see the whole organization. The workspace and template management endpoints apply the role rules of the console — Owner and Member can create and edit, Viewer and Analyst can read (see User Roles).

Errors return a standard Status object with a code (a google.rpc.Code value), a developer-facing message, and optional details — e.g. 404 maps to NOT_FOUND when a workspace or template does not exist, 400 to INVALID_ARGUMENT when a request is rejected at the API edge or by the sandbox operator.

Endpoints at a glance

APIEndpointWhat it does
WorkspacesGET /organizations/{organizationId}/workspacesList workspaces
WorkspacesPOST /organizations/{organizationId}/workspacesCreate a workspace
WorkspacesGET /organizations/{organizationId}/workspaces/{id}Get a workspace
WorkspacesPUT /organizations/{organizationId}/workspaces/{id}Create or update a workspace (upsert)
WorkspacesDELETE /organizations/{organizationId}/workspaces/{id}Delete a workspace
WorkspacesPOST /organizations/{organizationId}/workspaces/{id}:suspendSuspend a running workspace
WorkspacesPOST /organizations/{organizationId}/workspaces/{id}:resumeResume a suspended workspace
WorkspacesGET /organizations/{organizationId}/workspaces/{id}:costGet one workspace's cost over a period
WorkspacesGET /organizations/{organizationId}/workspaces:costReportGet a cost report over a period
WorkspacesGET /organizations/{organizationId}/workspaces:costPricesGet the effective cost unit prices
WorkspacesGET /organizations/{organizationId}/workspaces:getSecretMappingsGet the caller's effective secret mappings
TemplatesGET /organizations/{organizationId}/workspace-templatesList workspace templates
TemplatesPOST /organizations/{organizationId}/workspace-templatesCreate a workspace template
TemplatesGET /organizations/{organizationId}/workspace-templates/{id}Get a workspace template
TemplatesPATCH /organizations/{organizationId}/workspace-templates/{id}Update a workspace template (full replacement)
TemplatesDELETE /organizations/{organizationId}/workspace-templates/{id}Delete a workspace template
SessionsGET /organizations/{organizationId}/workspaces/-/sessionsList sessions across all workspaces
EventsGET /organizations/{organizationId}/workspaces/-/eventsList curated workspace events
EventsGET /organizations/{organizationId}/workspaces/{workspaceId}/usageGet a usage metric time series
TokensPOST /workspace-tokens:exchangeExchange an identity token for a workspace JWT
TokensPOST /workspace-tokens:verifyKeyVerify an API key's identity

Manage workspaces

Workspaces are the sandboxes themselves: a Workspace record owns its status, resource allocation, template reference, and secret injection state.

Workspace lifecycle

FieldMeaning
idThe workspace ID (assigned by the API)
statusINITIALIZING, ACTIVE, SUSPENDED, DELETING, TERMINATED, or FAILED
createTimeWhen the workspace was created
clusterThe cluster hosting the workspace
creatorIdThe user who created it
clientTypeWhat created it, e.g. harness
uriWebSocket URI for attaching to the workspace
hostIdentityPublicKeyHost identity key for SSH access

List workspaces

curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces?page.limit=20'

Optional query parameters: creatorId and clientType filter the listing; page.limit/page.cursor paginate; sort.field/sort.order order results (order defaults to ASC). The response is a ListWorkspacesResponse with an items array, totalCount, and nextPageCursor when more pages exist.

Create a workspace

Workspaces are usually provisioned from a template, which snapshots its preset values at creation time:

curl -X POST \
  -H 'X-API-Key: {KEY}' \
  -H 'Content-Type: application/json' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces' \
  -d '{
    "templateName": "python-dev",
    "description": "Feature branch sandbox"
  }'

Reference templates by templateName (resolved to whatever currently carries that name) or by templateId (pinned to an exact template). Set at most one; when both are set they must agree. On create, templateName/templateId conflict with explicit spec fields — specify one or the other, never both.

Alternatively, pass create-time parameters directly in spec:

curl -X POST \
  -H 'X-API-Key: {KEY}' \
  -H 'Content-Type: application/json' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces' \
  -d '{
    "spec": {
      "resources": { "cpu": "250m", "memory": "1Gi", "pvcSize": "20Gi" },
      "dependencies": ["jq", "node@22"],
      "egressPolicy": { "denyByDefault": true, "allowed": ["github.com", "registry.npmjs.org"] }
    }
  }'

spec fields: resources (Kubernetes quantity strings like 500m, 1Gi — unset fields inherit the organization policy), dependencies (CLI tools to install at boot, [registry:]tool[@version] grammar), egressPolicy (denyByDefault, allowed, denied), initScript (a shell script run at boot, 64 KiB cap), files (custom files written into the sandbox, home-relative paths), and secretMappings (environment variable to secret reference). On read, only resources is populated with the resolved values; the other fields are write-only create-time inputs and come back empty ([], {}, or null).

Get and update a workspace

curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces/{id}'

GET returns the current Workspace. PUT /workspaces/{id} creates or updates — on an existing workspace it is a read-modify-write: spec.resources is immutable after creation (different values are rejected), the template reference must be absent or equal to the stored value, and write-only spec fields are ignored. Deleting a workspace is DELETE /workspaces/{id}.

Suspend and resume

Suspend stops a running workspace (chargeable resources are released), resume brings it back:

curl -X POST -H 'X-API-Key: {KEY}' \
  https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces/{id}:suspend

curl -X POST -H 'X-API-Key: {KEY}' \
  https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces/{id}:resume

Workspace templates

Templates are organization-scoped presets that admins and owners curate so members can provision consistent workspaces. A WorkspaceTemplate carries a unique, immutable name (rename = delete and recreate), a description, and a spec mirroring the workspace create-time parameters. The full spec is returned on read — unlike Workspace.spec, template definitions are catalog content.

# Create a template
curl -X POST \
  -H 'X-API-Key: {KEY}' -H 'Content-Type: application/json' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspace-templates' \
  -d '{
    "name": "python-dev",
    "description": "Python sandbox with Node tooling",
    "spec": {
      "resources": { "cpu": "250m", "memory": "1Gi", "pvcSize": "20Gi" },
      "dependencies": ["python", "node@22", "jq"]
    }
  }'

# List templates
curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspace-templates'

# Update (full replacement — omitted fields are cleared; name is immutable)
curl -X PATCH \
  -H 'X-API-Key: {KEY}' -H 'Content-Type: application/json' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspace-templates/{id}' \
  -d '{ "name": "python-dev", "description": "Updated", "spec": { "dependencies": ["python", "node@22"] } }'
📘

A workspace resolves its template to a snapshot of values at creation time. Editing or deleting a template later affects only workspaces created afterwards — never workspaces that already exist.

Sessions, events, and usage

Sessions, events, and usage let you observe what is happening inside your workspaces.

List sessions

GET /organizations/{organizationId}/workspaces/-/sessions lists the live sandbox sessions across all workspaces (optionally filtered by clientType). Each WorkspaceSession reports its name, workspaceId, whether it is alive, startedTime, and the agentMode it runs under (RPC, ACP, or PTY).

curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces/-/sessions'

List workspace events

GET /organizations/{organizationId}/workspaces/-/events returns curated, customer-facing events — creation timeline, health, and lifecycle — newest first. Filter with workspaceId (empty lists events for all workspaces), fromTime/toTime (defaults: now-7d to now), minSeverity (info default, warn, error), eventTypes (e.g. workspace.oom), and page parameters.

curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces/-/events?minSeverity=warn&workspaceId={id}'

Each event carries workspaceId, eventTime, eventType, severity, a customer-facing title, and details (whitelisted display fields like sandbox, pod, reason). Titles and details are final renderings produced at ingest — display them as-is.

Get usage metrics

GET /organizations/{organizationId}/workspaces/{workspaceId}/usage returns a pre-aggregated time series for one metric. Pick the metric from the full enum — CPU seconds, memory working set / max usage, network receive / transmit bytes, filesystem read / write bytes, CPU throttled periods, restarts total, PVC requested bytes — and the resolution (5m or 1h buckets). fromTime/toTime default to the last 24 hours. Counter metrics are returned as per-interval rates.

curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces/{workspaceId}/usage?metric=USAGE_METRIC_CPU_USAGE_SECONDS&resolution=RESOLUTION_1H'

Costs

Workspace costs are fixed-rate: unit prices multiplied by the workspace's resource requests and the overlap of its lifetime with the requested period. Deleted workspaces remain billable and appear in reports for the period they existed.

  • GET /workspaces/{id}:cost — one workspace's cost (cpuCost, memoryCost, storageCost, totalCost in USD). Missing window bounds default to the workspace's lifetime (create time to deletion time or now); a two-sided window entirely outside the lifetime yields zero costs.
  • GET /workspaces:costReport?startTime=...&endTime=... — per-workspace costs over a period (both bounds required) plus the totalCost across them. Visibility follows the caller's role: members see their own + org-wide shared workspaces, owners see the whole org.
  • GET /workspaces:costPrices — the effective unit prices the cost endpoints apply: the organization's override row when present, else the global default. Returns cpuHourly, memoryHourly, pvcHourly, and ephemeralHourly in USD.
curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces:costReport?startTime=2026-10-01T00:00:00Z&endTime=2026-11-01T00:00:00Z'

Secret mappings

GET /workspaces:getSecretMappings returns the caller's effective secret injection mappings — the environment variable name → secret reference map that CreateWorkspace injects when spec.secretMappings is unset. This is metadata only: secret values are never exposed by the API.

curl -H 'X-API-Key: {KEY}' \
  'https://api.cast.ai/ai-optimizer/v1beta/organizations/{organizationId}/workspaces:getSecretMappings'

Workspace token exchange

The token endpoints (note: no organizationId in the path) support machine-to-machine auth between Kimchi services and workspace infrastructure.

  • POST /workspace-tokens:exchange — exchange a Kimchi identity token for a short-lived, Ed25519-signed JWT scoped to one workspace ({"workspaceId": "..."}). Recipients verify it against the public key at /.well-known/jwks.json. The response carries the token and its expireTime; treat the token as expired slightly before that time to account for clock skew.
  • POST /workspace-tokens:verifyKey — read-only introspection: returns the canonical identity (organizationId, userId) associated with the API key used to authenticate the call.
curl -X POST \
  -H 'Authorization: Bearer {IDENTITY_TOKEN}' \
  -H 'Content-Type: application/json' \
  'https://api.cast.ai/ai-optimizer/v1beta/workspace-tokens:exchange' \
  -d '{ "workspaceId": "{id}" }'

See also


Did this page help you?