API
Base URL: http://localhost:8080 (configurable via server-config.yaml)
Task, job, and log endpoints do not require authentication unless the server is configured with an auth section. When ACL is configured, list endpoints (tasks, jobs, workspaces) are filtered based on user permissions. See Authorization for details.
List Workspaces
Section titled “List Workspaces”GET /api/workspacesReturns all configured workspaces with task and action counts.
Response:
[ { "name": "default", "tasks_count": 3, "actions_count": 5, "triggers_count": 1, "revision": "abc123" }]List Tasks
Section titled “List Tasks”GET /api/workspaces/{ws}/tasksReturns all tasks from the specified workspace.
| Parameter | Description |
|---|---|
ws | Workspace name |
Response:
[ { "name": "hello-world", "workspace": "default", "mode": "distributed", "has_triggers": true }]The folder field is included when set on the task. has_triggers is true when at least one enabled trigger targets this task.
Get Task Detail
Section titled “Get Task Detail”GET /api/workspaces/{ws}/tasks/{name}| Parameter | Description |
|---|---|
ws | Workspace name |
name | Task name |
Response:
{ "name": "hello-world", "mode": "distributed", "input": { "name": { "type": "string", "default": "World" } }, "flow": { "say-hello": { "action": "greet", "input": { "name": "{{ input.name }}" } } }, "triggers": [ { "name": "nightly", "type": "scheduler", "cron": "0 0 2 * * *", "task": "hello-world", "enabled": true, "input": {}, "next_runs": ["2026-02-19T02:00:00+00:00"] } ]}The triggers array contains all triggers targeting this task. Scheduler triggers include next_runs with the next 5 upcoming fire times.
Execute Task
Section titled “Execute Task”POST /api/workspaces/{ws}/tasks/{name}/executeCreates a new job for the given task.
| Parameter | Description |
|---|---|
ws | Workspace name |
name | Task name |
Request body:
{ "input": { "name": "World" }}Response:
{ "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}List Triggers
Section titled “List Triggers”GET /api/workspaces/{ws}/triggersReturns all triggers in the workspace with upcoming fire times for cron-based triggers.
Response:
[ { "name": "nightly", "type": "scheduler", "cron": "0 0 2 * * *", "task": "nightly-backup", "enabled": true, "input": { "env": "production" }, "next_runs": ["2026-02-19T02:00:00+00:00"] }]List Jobs
Section titled “List Jobs”GET /api/jobs| Query parameter | Default | Description |
|---|---|---|
workspace | — | Filter by workspace name |
task_name | — | Filter by task name (requires workspace) |
limit | 50 | Number of jobs to return |
offset | 0 | Pagination offset |
Response:
{ "items": [ { "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "workspace": "default", "task_name": "hello-world", "mode": "distributed", "status": "completed", "source_type": "api", "source_id": null, "revision": "abc123def456", "created_at": "2025-02-10T12:00:00Z", "started_at": "2025-02-10T12:00:01Z", "completed_at": "2025-02-10T12:00:03Z" } ], "total": 1}Source types: "api", "user", "trigger", "webhook", "hook", "task"
Job statuses: pending, running, completed, failed, cancelled
Get Job Detail
Section titled “Get Job Detail”GET /api/jobs/{id}Returns job metadata and all steps with statuses.
| Parameter | Description |
|---|---|
id | Job ID (UUID) |
Response:
{ "job_id": "a1b2c3d4-...", "workspace": "default", "task_name": "hello-world", "status": "completed", "revision": "abc123def456", "input": { "name": "World" }, "steps": [ { "step_name": "say-hello", "action_name": "greet", "action_type": "script", "runner": "local", "input": { "name": "World" }, "output": { "greeting": "Hello World" }, "status": "completed", "worker_id": "w1w2w3w4-...", "started_at": "2025-02-10T12:00:01Z", "completed_at": "2025-02-10T12:00:02Z", "error_message": null } ]}Step statuses: pending, ready, running, completed, failed, skipped, cancelled
Cancel Job
Section titled “Cancel Job”POST /api/jobs/{id}/cancelCancels a pending or running job. Running steps are actively killed (processes terminated, containers stopped, pods deleted). Pending steps are marked as cancelled. Child jobs are recursively cancelled. Fires on_error hooks.
| Parameter | Description |
|---|---|
id | Job ID (UUID) |
Response (200):
{ "status": "cancelled"}Error responses:
| Status | Description |
|---|---|
404 | Job not found |
409 | Job is already in a terminal state (completed, failed, or cancelled) |
CLI:
stroem cancel <job_id>Get Job Logs
Section titled “Get Job Logs”GET /api/jobs/{id}/logsReturns combined log output from all steps in JSONL format.
Response:
{ "logs": "{\"ts\":\"...\",\"stream\":\"stdout\",\"step\":\"say-hello\",\"line\":\"Hello World\"}\n"}Get Step Logs
Section titled “Get Step Logs”GET /api/jobs/{id}/steps/{step}/logsReturns JSONL log output for a specific step. Use _server as the step name for server-side events.
Stream Job Logs (WebSocket)
Section titled “Stream Job Logs (WebSocket)”GET /api/jobs/{id}/logs/streamOpens a WebSocket connection for real-time log streaming. Sends existing content (backfill) on connect, then streams new chunks.
websocat ws://localhost:8080/api/jobs/JOB_ID/logs/streamList Users
Section titled “List Users”GET /api/usersReturns registered users with their authentication methods. Supports limit and offset query parameters. Response: { "items": [...], "total": N }.
Get User Detail
Section titled “Get User Detail”GET /api/users/{id}Returns a single user’s info including authentication methods and groups.
User Management (Admin Only)
Section titled “User Management (Admin Only)”The following endpoints require admin privileges (is_admin: true). Non-admin users receive a 403 Forbidden response.
List Users
Section titled “List Users”GET /api/usersReturns registered users with pagination.
| Query parameter | Default | Description |
|---|---|---|
limit | 20 | Number of users to return |
offset | 0 | Pagination offset |
Response:
{ "items": [ { "id": "user-uuid-...", "email": "alice@example.com", "is_admin": true, "groups": ["devops", "admin"] } ], "total": 1}Get User Detail
Section titled “Get User Detail”GET /api/users/{id}Returns a single user’s info including admin flag and group memberships.
Response:
{ "id": "user-uuid-...", "email": "alice@example.com", "is_admin": true, "groups": ["devops"]}Set Admin Flag
Section titled “Set Admin Flag”PUT /api/users/{id}/adminGrants or revokes admin privileges.
Request body:
{ "is_admin": true}Response (200):
{ "is_admin": true}Set User Groups
Section titled “Set User Groups”PUT /api/users/{id}/groupsUpdates the user’s group memberships.
Request body:
{ "groups": ["devops", "qa"]}Response (200):
{ "groups": ["devops", "qa"]}List Groups
Section titled “List Groups”GET /api/groupsReturns all distinct group names in use.
Response:
["admin", "devops", "qa"]List Workers
Section titled “List Workers”GET /api/workersReturns registered workers with status and tags. Supports limit and offset query parameters. Response: { "items": [...], "total": N }.
Get Worker Detail
Section titled “Get Worker Detail”GET /api/workers/{id}Returns a single worker’s info along with its recent steps (up to 50).
Response:
{ "steps": { "items": [ { "job_id": "...", "workspace": "...", "task_name": "...", "job_status": "...", "step_name": "...", "action_type": "...", "status": "...", "started_at": "...", "completed_at": "...", "error_message": null } ], "total": 42 }}Error responses
Section titled “Error responses”All endpoints return errors in a consistent format:
{ "error": "Description of what went wrong"}| Status | Description |
|---|---|
400 | Bad request (invalid input, missing fields) |
401 | Unauthorized (missing or invalid token) |
404 | Not found (unknown task, job, or step) |
409 | Conflict (e.g., cancelling an already-terminal job) |
500 | Internal server error |