Manage workspaces
Create, inspect, edit, and delete workspaces; list the regions you can create in.
Create a workspace
Only name is required. Authorization is the only required header —
send X-Workspace-Id too if you're working inside an organization
workspace and want the new workspace attached to the same organization:
curl -X POST "$API_BASE/v1/workspace" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Demand forecasting",
"description": "Daily demand across EU markets",
"goal": "Forecast SKU-level demand 14 days out",
"keywords": ["demand", "retail", "sku"],
"sectors": ["retail"],
"data_granularity": "day",
"region": "eu-1"
}'from predictai import PredictAI
client = PredictAI(token="pa_live_…")
data = client.workspaces.post_workspace(json={
"name": "Demand forecasting",
"description": "Daily demand across EU markets",
"goal": "Forecast SKU-level demand 14 days out",
"keywords": ["demand", "retail", "sku"],
"sectors": ["retail"],
"data_granularity": "day",
"region": "eu-1",
})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…" });
const data = await client.workspaces.postWorkspace({
json: {
name: "Demand forecasting",
description: "Daily demand across EU markets",
goal: "Forecast SKU-level demand 14 days out",
keywords: ["demand", "retail", "sku"],
sectors: ["retail"],
data_granularity: "day",
region: "eu-1",
},
});
{
"data": {
"uid": "7d4a9b2e-3c61-4f8a-9e27-5b0c8d1f6a42",
"expires_at": null,
"message": "Workspace created successfully"
}
}A 201 means the workspace exists — the uid is the value you'll send as
X-Workspace-Id from now on. expires_at is null for a permanent
workspace; see ephemeral workspaces below.
| Field | What it is |
|---|---|
name required | Display name. |
description optional | Free text. |
goal optional | What you want to forecast (stored as purpose; either key is accepted). |
keywords optional | Array of lowercase strings. |
sectors optional | Array of lowercase strings. |
data_granularity optional | The cadence your data arrives at; defaults to day. |
region optional | Region ID from available regions. Defaults to your account's home region. Set once — a workspace never changes region. |
expires_at optional | ISO 8601 timestamp in the future. Makes the workspace ephemeral: it is deleted automatically once this time passes. Omit for a permanent workspace. |
Errors
| Status | Why | Example message |
|---|---|---|
400 | Empty body or missing name | "Missing required field: name" |
400 | region isn't a selectable region | "Region 'ap-9' is not available for selection." |
400 | expires_at is malformed or not in the future (invalid_expires_at) | "expires_at must be in the future" |
403 | Plan workspace quota reached | "Workspace limit exceeded. Your plan allows 5 workspaces." |
The invalid-region error comes back structured, with the valid choices inline:
{
"error": {
"code": "invalid_region",
"message": "Region 'ap-9' is not available for selection.",
"details": { "available_regions": [ { "id": "eu-1", … } ] }
},
"status": "Region 'ap-9' is not available for selection."
}Ephemeral workspaces
A workspace with an expires_at is ephemeral. In every other respect
it is an ordinary workspace — same features, same billing, same plan
limits and quotas — but once expires_at passes it is deleted, with
everything in it, by a collector that runs every 10 minutes. Billing
records are kept.
The caller owns the date. The platform never moves it: to keep an
ephemeral workspace alive, send a later expires_at with
edit; to keep it for good, send "expires_at": null.
Every workspace in list and
get responses carries expires_at (null when
permanent), and ephemeral workspaces are listed alongside permanent ones —
nothing is hidden.
# create a workspace that is deleted in 7 days unless kept
curl -X POST "$API_BASE/v1/workspace" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Scratch analysis", "expires_at": "2026-10-17T12:00:00Z" }'
# extend it by another week
curl -X PUT "$API_BASE/v1/workspace/$WORKSPACE_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "expires_at": "2026-10-24T12:00:00Z" }'
# keep it permanently
curl -X PUT "$API_BASE/v1/workspace/$WORKSPACE_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "expires_at": null }'Ephemeral workspaces suit anything short-lived: a one-off analysis, an agent's working space, a trial of the platform from a chat client. The MCP server creates one by default when you connect.
Get one workspace
curl "$API_BASE/v1/workspace/$WORKSPACE_ID" \
-H "Authorization: Bearer $TOKEN"from predictai import PredictAI
client = PredictAI(token="pa_live_…")
data = client.workspaces.get_workspace_by_workspace_id(WORKSPACE_ID)
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…" });
const data = await client.workspaces.getWorkspaceByWorkspaceId(WORKSPACE_ID);
{
"data": {
"uid": "7d4a9b2e-3c61-4f8a-9e27-5b0c8d1f6a42",
"name": "Demand forecasting",
"description": "Daily demand across EU markets",
"owner": "e1c62b7a-9f04-4d3b-8a15-2c7d90e4b638",
"created_at": "2026-06-02T09:14:00+00:00",
"updated_at": "2026-07-10T16:45:00+00:00",
"expires_at": null,
"collaborators": ["e1c62b7a-9f04-4d3b-8a15-2c7d90e4b638"],
"user_role": "owner",
"organization_name": "Acme Analytics",
"organization_owner": "e1c62b7a-9f04-4d3b-8a15-2c7d90e4b638"
}
}expires_at is an ISO 8601 timestamp for an
ephemeral workspace and null for a permanent
one. organization_name and organization_owner appear only when the
workspace belongs to an organization. Unlike the
list route, the detail view
carries no statistics block.
Errors
| Status | Why | Example message |
|---|---|---|
403 | You can't access this workspace | "Access denied to this workspace" |
404 | No such workspace | "Workspace with ID … not found" |
Edit a workspace
Send only the fields you're changing. The workspace owner or any collaborator can edit:
curl -X PUT "$API_BASE/v1/workspace/$WORKSPACE_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Demand forecasting (EU)" }'from predictai import PredictAI
client = PredictAI(token="pa_live_…")
data = client.workspaces.put_workspace_by_workspace_id(WORKSPACE_ID, json={"name": "Demand forecasting (EU)"})
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…" });
const data = await client.workspaces.putWorkspaceByWorkspaceId(WORKSPACE_ID, { json: { name: "Demand forecasting (EU)" } });
{ "data": { "message": "Workspace updated successfully", "expires_at": null } }| Field | Meaning |
|---|---|
name optional | Rename the workspace. |
description / purpose optional | Free-text metadata. |
keywords / sectors optional | Arrays of lowercase strings. |
data_granularity optional | The cadence your data arrives at. |
collaborators optional | The array of user IDs with direct access. |
expires_at optional | A future ISO 8601 timestamp sets or moves the expiry (ephemeral); null clears it and makes the workspace permanent. |
Anything else in the body is ignored. The response always carries the
resulting expires_at. If nothing actually changed, you get 200 with
"No changes were made to the workspace".
Errors
| Status | Why | Example message |
|---|---|---|
400 | Empty body | "Request body is empty" |
400 | expires_at is malformed or not in the future (invalid_expires_at) | "expires_at must be in the future" |
403 | Not the owner or a collaborator | "You don't have permission to edit this workspace" |
404 | No such workspace | "Workspace with ID … not found" |
Delete a workspace
Only the workspace owner can delete:
curl -X DELETE "$API_BASE/v1/workspace/$WORKSPACE_ID" \
-H "Authorization: Bearer $TOKEN"from predictai import PredictAI
client = PredictAI(token="pa_live_…")
data = client.workspaces.delete_workspace_by_workspace_id(WORKSPACE_ID)
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…" });
const data = await client.workspaces.deleteWorkspaceByWorkspaceId(WORKSPACE_ID);
{ "data": { "message": "Workspace and all related data deleted successfully" } }Deletion is immediate and irreversible, and it takes everything in
the workspace with it: in-flight trainings, inferences, and imports are
cancelled; live deployments are taken out of serving; then all models,
pipelines, segments, signals, events, goals, trainings, deployments,
inference history, chat transcripts and member grants are permanently
deleted. Billing records are kept. An ephemeral
workspace goes through exactly the same cascade
when its expires_at passes.
Errors
| Status | Why | Example message |
|---|---|---|
403 | Not the workspace owner | "You don't have permission to delete this workspace" |
404 | No such workspace | "Workspace with ID … not found" |
List available regions
The regions you may create a workspace in, plus the default the platform would pick for you:
curl "$API_BASE/v1/workspace/available-regions" \
-H "Authorization: Bearer $TOKEN"from predictai import PredictAI
client = PredictAI(token="pa_live_…")
data = client.workspaces.get_workspace_available_regions()
import { PredictAI } from "@predictai/sdk";
const client = new PredictAI({ token: "pa_live_…" });
const data = await client.workspaces.getWorkspaceAvailableRegions();
{
"data": {
"regions": [
{
"id": "eu-1",
"region": "eu-north-1",
"subdomain": "eu.api.predict.ai",
"countries": ["*EU"]
},
…
],
"default_region": "eu-1"
}
}Pass a region's id as the region field when
creating a workspace. subdomain is the API host
serving that region — your base URL for workspaces created there.
default_region is what you get when you don't choose; it's derived from
your account's (or organization's) stored country and home region. When
only one region is listed, there's nothing to decide.

