Workloads
Workloads are managed background processes running inside your workspace. Each workload has its own lifecycle (start/stop), logging, and status tracking.
Stable IDs and project labels
Set id when a project needs a stable workload identity inside a shared workspace.
IDs are unique within that workspace, and the same ID may be used in another
workspace. Create, get and list preserve the ID and labels, including after a
cold workspace restart. Omit id to generate the next available numeric ID.
An ID must contain 1–128 letters, numbers, dots, underscores or hyphens, starting
with a letter or number. labels accepts up to 64 string values; keys must be
1–128 bytes and values at most 1024 bytes. Invalid input returns HTTP 400 with
invalid_workload_id or invalid_workload_labels.
Creating the same ID again returns HTTP 409 / workload_id_conflict. It does
not replace the command, labels or running process. On an ambiguous network
failure, get the requested ID and verify its configuration before deciding to
update it. Labels describe a workload; they do not grant access or change the
workspace's account or namespace ownership. Workspace permissions apply to all
workloads in that workspace; use separate workspaces for customers that must not
control each other's processes.
const workload = await ws.workloads.create('ws_a1b2c3d4', {
id: 'project-42-web',
cmd: ['node', 'server.js'],
labels: { project: '42', role: 'web' },
});
const sameWorkload = await ws.workloads.get('ws_a1b2c3d4', workload.id);REST create/get responses wrap the object in workload; list responses use
workloads. The SDK returns the workload object or array directly.
Log retention and cleanup
Managed workload logs have bounded retention. By default, each workload keeps up to 20 MiB across two files, for up to 7 days. Size rotation may remove records sooner. Very high output rates can drop excess lines; these logs are a recent operational history, not an archival logging service.
Set these fields when creating a workload, or send them to PATCH /workspace/:workspaceId/workloads/:workloadId:
| Field | Default | Allowed values |
|---|---|---|
max_log_size_mb | 10 | 1–64 MiB per file; two files retained |
log_retention_hours | 168 | 1–720 hours |
Zero resets a field to its bounded default; it does not disable retention. Reducing a limit can delete older output immediately. Updating retention requires a running workspace and does not restart the workload.
PATCH /workspace/:workspaceId/workloads/:workloadId
Content-Type: application/json
{"max_log_size_mb": 5, "log_retention_hours": 24}Use the normal workspace API credentials for these endpoints:
| Operation | Endpoint |
|---|---|
| Applied limits, stored bytes and dropped-output count | GET /workspace/:workspaceId/workloads/:workloadId/logs/config |
| Delete retained workload logs | DELETE /workspace/:workspaceId/workloads/:workloadId/logs |
| Recent history, at most the requested number of lines | GET /workspace/:workspaceId/workloads/:workloadId/logs?tail=2000 |
Clearing logs removes both retained files' contents and keeps the process running. New output appears immediately. The dropped-output count covers this agent run. A live stream sends cleared: true when history is cleared; viewers should discard older entries when they receive it. Slow viewers may disconnect and can reconnect to fetch the retained tail.
In the dashboard, open a workload's logs and use Log retention or Clear stored logs. The viewer retains at most 2,000 entries and 1 MiB. Pausing the viewer disconnects its stream; resuming loads the retained tail.
The SDK helpers are workloads.logConfig(), workloads.clearLogs(), and workloads.update() with the fields above. If your installed SDK does not yet include these helpers, use the REST endpoints. Older workspace agents return an explicit update-required error for these controls.
Create
Create and start a new workload.
const workload = await ws.workloads.create('ws_a1b2c3d4', {
cmd: ['node', 'server.js'],
name: 'web-server',
labels: { role: 'api', env: 'production' },
});POST /workspace/:workspaceId/workloads{
"cmd": ["node", "server.js"],
"name": "web-server",
"labels": { "role": "api", "env": "production" }
}curl -X POST "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"cmd": ["node", "server.js"],
"name": "web-server",
"labels": { "role": "api" }
}'Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
cmd | string[] | Yes | Command array (non-empty) |
command | string[] | - | Alias for cmd |
id | string | No | Stable workspace-scoped ID; generated if omitted; duplicate IDs return 409 |
name | string | No | Human-readable workload name |
labels | Record<string, string> | No | Up to 64 metadata labels, persisted with the workload |
Response 201
{
"success": true,
"workload": {
"id": "wl_xyz789",
"name": "web-server",
"command": ["node", "server.js"],
"labels": { "role": "api", "env": "production" },
"state": "running",
"created_at": "2026-02-24T10:30:00Z"
}
}List
List all workloads. Supports filtering by state, name, and labels.
const workloads = await ws.workloads.list('ws_a1b2c3d4', {
states: 'running',
name: 'web',
});GET /workspace/:workspaceId/workloads?states=running&name=webcurl "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads?states=running" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Query parameters
| Parameter | Type | Description |
|---|---|---|
states | string | Filter by state (e.g., "running", "stopped") |
name | string | Filter by name (partial match) |
label_* | string | Filter by label. e.g., label_role=api |
Get
Get a specific workload.
const workload = await ws.workloads.get('ws_a1b2c3d4', 'wl_xyz789');GET /workspace/:workspaceId/workloads/:workloadIdcurl "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Update
Update a workload's configuration.
await ws.workloads.update('ws_a1b2c3d4', 'wl_xyz789', {
name: 'web-server-v2',
labels: { version: '2.0' },
});PUT /workspace/:workspaceId/workloads/:workloadId{
"name": "web-server-v2",
"labels": { "version": "2.0" }
}curl -X PUT "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{ "name": "web-server-v2" }'Delete
Delete a specific workload.
await ws.workloads.delete('ws_a1b2c3d4', 'wl_xyz789');DELETE /workspace/:workspaceId/workloads/:workloadIdcurl -X DELETE "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Delete all
Delete all workloads in the workspace.
await ws.workloads.deleteAll('ws_a1b2c3d4');DELETE /workspace/:workspaceId/workloadscurl -X DELETE "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Start
Start a stopped workload.
await ws.workloads.start('ws_a1b2c3d4', 'wl_xyz789');POST /workspace/:workspaceId/workloads/:workloadId/startcurl -X POST "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789/start" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Stop
Stop a running workload.
await ws.workloads.stop('ws_a1b2c3d4', 'wl_xyz789');POST /workspace/:workspaceId/workloads/:workloadId/stopcurl -X POST "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789/stop" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Status
Get the current status of a workload.
const status = await ws.workloads.status('ws_a1b2c3d4', 'wl_xyz789');GET /workspace/:workspaceId/workloads/:workloadId/statuscurl "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789/status" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Logs
Get logs for a workload.
const logs = await ws.workloads.logs('ws_a1b2c3d4', 'wl_xyz789');GET /workspace/:workspaceId/workloads/:workloadId/logscurl "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789/logs" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Stream logs
Stream workload logs in real-time via SSE (Server-Sent Events).
for await (const entry of ws.workloads.logsStream('ws_a1b2c3d4', 'wl_xyz789')) {
console.log(entry.line);
}GET /workspace/:workspaceId/workloads/:workloadId/logs/streamReturns an SSE stream with 15-second heartbeat. Initial comment: :ok\n\n
:ok
data: {"line":"Server started on port 3000","timestamp":"2026-02-24T10:30:01Z"}
data: {"line":"GET / 200 12ms","timestamp":"2026-02-24T10:30:05Z"}curl -N "https://api.oblien.com/workspace/ws_a1b2c3d4/workloads/wl_xyz789/logs/stream" \
-H "X-Client-ID: $OBLIEN_CLIENT_ID" \
-H "X-Client-Secret: $OBLIEN_CLIENT_SECRET"Close the connection to stop streaming.