API Reference
The RunWhen Platform API gives you programmatic access to your workspaces, observability data, automation workflows, and troubleshooting tools. Use it to integrate RunWhen into your existing toolchains, build custom dashboards, or automate operational tasks at scale.
Getting Started
Base URL
The Platform API is served by PAPI, on the papi. hostname — not the app. web-app host:
https://papi.<domain>| Deployment | <domain> | Host |
|---|---|---|
| RunWhen SaaS (beta) | beta.runwhen.com | https://papi.beta.runwhen.com |
| Self-hosted | your global.domain Helm value | https://papi.<your-domain> |
The API spans multiple versions, so every path includes its version prefix (/api/v3, and for a few resources /api/v1 or /api/v4). Most endpoints are v3; Knowledge Base Notes and Assistants are v4; custom-task commit is v1. Each endpoint table below lists the full path.
Self-hosted: override the entire host with your own
papi.<domain>. In the interactive reference, edit thedomainserver variable; in the examples below, set theBASE/RW_BASEvariable accordingly.
Wrong host = 404. Requests to the
app.host (e.g.https://app.beta.runwhen.com/api/v3/…) return404for every endpoint — that host serves the web UI, not the API. Usepapi.<domain>.
Authentication
The RunWhen API authenticates requests using JSON Web Tokens (JWT). To get started:
- Obtain a token by calling
POST /api/v3/token/with your credentials. The endpoint accepts both JSON and form-urlencoded payloads for compatibility with service accounts and CLI tools. - Include the token in the
Authorizationheader of every request:
Authorization: Bearer <your-access-token>- Refresh transparently — access tokens are short-lived. Use the refresh token from the initial response to obtain new access tokens via
POST /api/v3/token/refresh/without re-authenticating.
For full endpoint details, see the Authentication section in the child pages below.
Service account tokens (automation)
For scripts, CI, and integrations that should not use a human user’s credentials, workspace admins can create service account tokens — dedicated JWT credentials scoped to a workspace:
| Method | Path | Purpose |
|---|---|---|
GET | /api/v3/workspaces/{workspace}/service-account-tokens | List tokens for this workspace |
POST | /api/v3/workspaces/{workspace}/service-account-tokens | Create a token (returns the JWT once in token) |
GET | /api/v3/workspaces/{workspace}/service-account-tokens/{tokenId} | Get token metadata |
POST | /api/v3/workspaces/{workspace}/service-account-tokens/{tokenId}/revoke | Revoke a token |
DELETE | /api/v3/workspaces/{workspace}/service-account-tokens/{tokenId} | Delete a token and its backing service-account user |
PUT | /api/v3/workspaces/{workspace}/service-account-tokens/{tokenId}/scopes | Replace workspace scopes (multi-workspace tokens) |
DELETE | /api/v3/workspaces/{workspace}/service-account-tokens/{tokenId}/scopes/{workspaceId} | Remove one workspace scope |
The caller must be a workspace admin of the workspace in the URL path. Use the returned JWT as Authorization: Bearer <token> on PAPI and AgentFarm the same way as a user access token.
Not the same as
{workspace}-sa. Each workspace also has a built-in service account user ({workspace}-sa) whose password is managed viaPOST /api/v3/workspaces/{workspace}/reset-service-accountand exchanged for a JWT atPOST /api/v3/token/. The endpoints above create named API tokens with an explicit role and expiry for the workspace in the path.
Example create:
curl -sS -X POST "$BASE/api/v3/workspaces/$WS/service-account-tokens" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "ci-readonly", "role": "readonly", "expiresInDays": 90 }'Store the token field from the response — it is not returned again.
Core Concepts
Workspaces
A Workspace is the top-level container for all RunWhen resources. Every SLX, RunSession, issue, workflow, and persona belongs to a workspace. Workspaces map to a specific environment, team, or operational scope and are backed by a Git repository that stores their declarative configuration.
SLXs (Service Level Expectations)
An SLX defines what “healthy” looks like for a service or component. Each SLX can contain:
- SLI (Service Level Indicator) — the metric being measured
- SLO (Service Level Objective) — the target threshold for that metric
- Runbook — the automated remediation or diagnostic action to take when the SLO is breached
SLX identifiers use a short name format in the API (e.g., check-cpu-usage). The workspace prefix is handled automatically based on the URL path — you never need to pass the full internal name.
RunSessions & RunRequests
A RunSession groups one or more RunRequests into a single diagnostic or remediation workflow. RunSessions can be initiated by users, alerts, Slack commands, workflows, or API calls. Each RunRequest represents the execution of a specific runbook task against an SLX.
Issues & Occurrences
Issues are problems or anomalies detected during RunSessions. The platform tracks repeat detections as Occurrences and can generate AI-powered JIT Summaries with root cause analysis and recommended next steps.
Workflows & Personas
Workflows define event-driven or on-demand automation — triggered by alerts, webhooks, or manual invocation. Personas are AI assistants configured with domain-specific expertise, confidence thresholds, and filtering rules that determine how they respond to issues.
CodeCollections & CodeBundles
CodeCollections are Git repositories containing CodeBundles — reusable troubleshooting and automation scripts written in Robot Framework. They power the SLIs, SLOs, and Runbooks across the platform.
Task Search
Task Search provides semantic, vector-based search for finding the most relevant troubleshooting tasks and CodeBundles based on a natural language description of the problem.
Conventions
| Convention | Details |
|---|---|
| Content-Type | application/json for all request and response bodies |
| Field naming | camelCase (e.g., slxName, createdAt, runSession) |
| Timestamps | ISO 8601 with timezone (e.g., 2026-03-01T12:00:00Z) |
| Identifiers | Integer primary keys |
| Pagination | List responses use a standard envelope: { count, next, previous, results } |
| Page navigation | Use the page query parameter (some endpoints also support page-size) |
Status Codes
| Code | Meaning |
|---|---|
200 OK | Request succeeded |
201 Created | Resource created successfully |
204 No Content | Resource deleted successfully |
400 Bad Request | Invalid request body or parameters |
401 Unauthorized | Missing or invalid authentication token |
403 Forbidden | Insufficient permissions for the requested resource |
404 Not Found | Resource does not exist |
429 Too Many Requests | Rate limit exceeded — implement exponential backoff |
500 Internal Server Error | Server-side error |
API Reference
Detailed endpoint documentation is organized by resource. Select a topic below to view available operations, parameters, and example responses.
| Resource | Description |
|---|---|
| Workspaces | Retrieve and manage workspaces, configuration uploads, health, and status |
| SLXs, SLIs, SLOs & Runbooks | Query observability primitives — expectations, indicators, objectives, and runbook definitions |
| RunSessions & RunRequests | Create diagnostic sessions, execute runbook tasks, and track execution status |
| Issues | View, update, and analyze detected issues with AI-powered JIT summaries |
| Workflows & Personas | Manage automation workflows, trigger execution, and configure AI personas |
| CodeCollections & CodeBundles | Browse code repositories, branches, CodeBundle metadata, and statistics |
| Users | User profiles, search, activity feeds, and workspace membership |
| Task Search & Activities | Semantic task search and workspace activity tracking |
| Operational Context | Knowledge Base notes, chat Rules, chat Commands, and Assistants — the programmatic equivalent of the Building Operational Context guide |
| Custom Tasks & Tool Builder | Author/test task scripts on a runner and commit them as SLXs |
| Service Account Tokens | Admin-managed JWT credentials for automation (PAPI) |
| Workspace Chat (AgentFarm) | Start, stream, abort, and export AI chat sessions |
Managing Operational Context
The Building Operational Context guide describes adding Rules, Commands, Knowledge, Assistants, and Custom Tasks through Workspace Studio. Every one of those actions has an API equivalent, so you can manage context as part of an engineering workflow — scripted bootstrap, CI/CD reconciliation, or migration between workspaces.
If you want to keep context definitions in your own Git repository and apply them automatically, see Managing Context as Code (GitOps).
All endpoints below are workspace-scoped and require an authenticated token. Writes to workspace- and persona-scoped Rules and Commands (and to Assistants and Custom Tasks) require the workspace admin role; user-scoped items only require workspace membership.
The examples use these shell variables — set BASE to your papi.<domain> host (see Base URL):
BASE="https://papi.beta.runwhen.com" # self-hosted: https://papi.<your-domain>WS="my-workspace"TOKEN="<your-access-token>"Knowledge Base (Notes)
Knowledge Base notes are the institutional context AI Assistants consult during investigations. Notes are workspace-scoped; any workspace member can create and manage notes through the CRUD API. Leave resourcePaths empty for a global note (loaded in every investigation) or set them to scope the note to specific resources. Use resourceSelectors with tag matchTags to attach a note to every resource carrying a given tag — the match set stays current as new resources are discovered.
Notes synced from an external source (git, CI/CD — see Managing Context as Code) are read-only in the CRUD API; edit them at the source and re-sync.
Notes CRUD is v4. The older v3 CRUD endpoints are retired. All note operations — create, read, update, delete, list — use the
/api/v4path prefix. Field names are camelCase.
CRUD
Workspace member access. Note noteId values are UUIDs.
| Method | Path | Purpose |
|---|---|---|
GET | /api/v4/workspaces/{workspace}/notes | List notes (`view=full |
POST | /api/v4/workspaces/{workspace}/notes | Create a note |
GET | /api/v4/workspaces/{workspace}/notes/{noteId} | Get a note |
PATCH | /api/v4/workspaces/{workspace}/notes/{noteId} | Update a note (partial — omitted fields are left unchanged) |
DELETE | /api/v4/workspaces/{workspace}/notes/{noteId} | Delete a note (rejected with 409 if the note is synced from an external source) |
Note bodies use camelCase fields. Example create:
curl -X POST "$BASE/api/v4/workspaces/$WS/notes" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "payments-ownership", "content": "The payments service is owned by the Commerce team. Always check open change requests in ServiceNow before diagnosing payment errors.", "resourcePaths": ["kubernetes/prod/cluster-01/namespace/payments"], "status": "active" }'Example with resourceSelectors (tag-based scoping):
curl -X POST "$BASE/api/v4/workspaces/$WS/notes" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "checkout-api-ownership", "content": "The checkout API is owned by the Commerce team — contact #commerce-oncall for escalations.", "resourceSelectors": [ {"matchTags": {"[k8s]app.kubernetes.io/name": "checkout-api"}} ], "status": "active" }'Import (Sync)
Workspace admin access. Publish and remove notes from an external source of truth (git, CI/CD). Synced notes are read-only in the CRUD API. Responses include diagnostics for schema/content validation and resourcePaths/resourceSelectors resolution previews. See the Knowledge as code guide for the full GitOps workflow.
| Method | Path | Purpose |
|---|---|---|
POST | /api/v4/workspaces/{workspace}/notes/sync | Upsert one note identified by its sourceKind/source/sourceId. dryRun=true validates without writing. Returns status (created/updated/unchanged/rejected), ok, noteId, and diagnostics. |
DELETE | /api/v4/workspaces/{workspace}/notes | Delete a batch of notes from one source by sourceIds. dryRun=true previews without deleting. Returns per-sourceId results (deleted/not_found). |
# Validate a note sync (dry run)curl -sS -X POST "$BASE/api/v4/workspaces/$WS/notes/sync" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{ "sourceKind": "git", "source": "'"$(git config --get remote.origin.url)"'", "sourceId": ".runwhen/knowledgebase/payments/5xx-triage.md", "sourceRef": "'"$(git rev-parse HEAD)"'", "content": "---\ntitle: payments-5xx-triage\nresource_paths:\n - kubernetes/prod/cluster-01/namespace/payments\n---\n\nWhen checkout returns 503s, first check connection-pool saturation.", "dryRun": true }'Discovery
Workspace member access. Query the workspace’s valid resource paths and tag keys/values to author resourcePaths and resourceSelectors against.
| Method | Path | Purpose |
|---|---|---|
GET | /api/v4/workspaces/{workspace}/resource-paths | List the workspace’s valid resource paths |
GET | /api/v4/workspaces/{workspace}/tags | List tag keys and sample values. limitValues (1–1000, default 100) caps the number of values returned per key. |
Rules
Rules are loaded directly into the assistant’s prompt context and shape how findings are interpreted (de-prioritize known noise, highlight real risk).
| Method | Path | Purpose |
|---|---|---|
GET | /api/v3/workspaces/{workspace}/chat-config/rules | List rules (filter by scope_type, scope_id, is_active) |
POST | /api/v3/workspaces/{workspace}/chat-config/rules | Create a rule |
GET | /api/v3/workspaces/{workspace}/chat-config/rules/{ruleId} | Get a rule |
PUT | /api/v3/workspaces/{workspace}/chat-config/rules/{ruleId} | Update a rule |
DELETE | /api/v3/workspaces/{workspace}/chat-config/rules/{ruleId} | Delete a rule |
GET | /api/v3/workspaces/{workspace}/chat-config/resolved | Resolved rules + commands an assistant will load (optional persona_name) |
Rule and Command bodies use snake_case fields. Example create:
curl -X POST "$BASE/api/v3/workspaces/$WS/chat-config/rules" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "deprioritize-node-pressure", "rule_content": "Mention node pressure briefly, but prioritize application-level impact first unless pressure correlates with a user symptom.", "scope_type": "workspace", "is_active": true }'Commands
Commands (slash-commands) package a repeatable investigation procedure. Set cron_schedule to run a command on a schedule and deliver the artifact to sink_configs.
| Method | Path | Purpose |
|---|---|---|
GET | /api/v3/workspaces/{workspace}/chat-config/commands | List commands |
POST | /api/v3/workspaces/{workspace}/chat-config/commands | Create a command |
GET | /api/v3/workspaces/{workspace}/chat-config/commands/{commandId} | Get a command |
PUT | /api/v3/workspaces/{workspace}/chat-config/commands/{commandId} | Update a command |
DELETE | /api/v3/workspaces/{workspace}/chat-config/commands/{commandId} | Delete a command |
POST | /api/v3/workspaces/{workspace}/chat-config/commands/{commandId}/run-now | Trigger a scheduled command immediately |
Scope types
Rules and Commands are scoped. Both workspace- and persona-level context are always loaded for matching assistants.
| Scope | scope_type | scope_id | Who can write |
|---|---|---|---|
| Workspace | workspace | (ignored — derived from URL) | Workspace admin |
| Assistant / persona | persona | Persona short name | Workspace admin |
| User | user | (forced to the caller’s email) | Any workspace member |
Assistants
Assistants (personas) tailor how the AI investigates and acts. The Assistant CRUD endpoints are v4. The create/update endpoint is a full upsert (sync-typed) — omitted fields reset to defaults, so read the current persona and merge for a partial update. An assistant’s short name is the persona_name used in workspace chat and the scope_id for persona-scoped Rules and Commands.
| Method | Path | Purpose |
|---|---|---|
GET | /api/v4/workspaces/{workspace}/personas | List assistants |
GET | /api/v4/workspaces/{workspace}/personas/{personaShortName} | Get an assistant |
POST | /api/v4/workspaces/{workspace}/personas/sync-typed | Create or update an assistant (upsert) |
DELETE | /api/v4/workspaces/{workspace}/personas/{personaShortName} | Delete an assistant |
Assistant payloads use camelCase and are wrapped in a payload envelope. The name is the full persona name {workspace}--{shortName}. Example create:
curl -X POST "$BASE/api/v4/workspaces/$WS/personas/sync-typed" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "payload": { "name": "'"$WS"'--azure-devops", "fullName": "Azure DevOps Helper", "description": "Specialist for Azure DevOps and AKS investigations.", "filterCodebundleTaskTags": ["azure", "devops"], "filterConfidenceThreshold": 0.5, "runConfidenceThreshold": 0.95 } }'After creating the assistant, shape its behavior with persona-scoped Rules and Commands (scope_type: "persona", scope_id: "azure-devops").
Custom Tasks (SLXs)
Custom tasks are SLXs — a task script plus its CodeBundle reference, configuration, and secrets. The recommended path to author one is the runwhen-platform-mcp Tool Builder (validate_script → run_script_and_wait → commit_slx), which validates and tests the script on a runner before committing. The underlying API is documented here for automation; see also Managing Context as Code (GitOps) and Tasks & Runbooks.
Read:
| Method | Path | Purpose |
|---|---|---|
GET | /api/v3/workspaces/{workspace}/slxs/ | List SLXs |
GET | /api/v3/workspaces/{workspace}/slxs/{slxName}/ | Get an SLX |
GET | /api/v3/workspaces/{workspace}/slxs/{slxName}/runbook | Get the runbook (tasks) for an SLX |
Commit (upsert) — sync the SLX first, then its Runbook (and optional SLI). The Runbook/SLI payloads reference the resource_id returned by the SLX sync:
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/workspaces/{workspace}/slxs/sync | Create or update an SLX |
POST | /api/v1/workspaces/{workspace}/runbooks/sync | Create or update the SLX’s Runbook (tasks) |
POST | /api/v1/workspaces/{workspace}/slis/sync | Create or update the SLX’s SLI |
DELETE | /api/v4/workspaces/{workspace}/slxs/{slxName} | Delete an SLX |
There is no per-workspace Git repo — the platform is CRD-less.
slxs/syncupserts the SLX straight into the platform (changes apply immediately). The task code lives in a codebundle Git repo referenced bycode_bundle_repo_url/code_bundle_path/code_bundle_ref(the registry or your own repo). Prefer the MCP Tool Builder, which tests on a runner before commit. See the GitOps guide for uploading a custom bash/python tool from CI.
Tool Builder (author runs)
The Tool Builder executes a script on a runner for testing before you commit it. Poll status until it leaves RUNNING, then fetch output.
| Method | Path | Purpose |
|---|---|---|
POST | /api/v3/workspaces/{workspace}/author/run | Run a task/SLI script on a runner (returns run_id) |
GET | /api/v3/workspaces/{workspace}/author/run/{runId}/status | Poll run status (RUNNING, SUCCEEDED, FAILED) |
GET | /api/v3/workspaces/{workspace}/author/run/{runId}/output | Parsed output — issues, stdout, stderr, report |
Workspace Configuration (supporting reads)
Discovery endpoints used when authoring tasks or building context:
| Method | Path | Purpose |
|---|---|---|
GET | /api/v3/workspaces/{workspace}/secrets-keys | List secret key names (not values) for secretVars mapping |
GET | /api/v3/workspaces/{workspace}/runners | List runner locations for script execution |
GET | /api/v3/workspaces/{workspace}/runner-token?location={location} | Get a runner registration token (admin only) — enroll a new runner at location |
GET | /api/v3/workspaces/{workspace}/workspace-configuration-index | Full config overview — resources, SLXs, and relationships |
POST | /api/v3/workspaces/{workspace}/autocomplete | Lightweight keyword autocomplete (use workspace chat for richer search) |
Workspace Chat (AgentFarm)
Workspace Chat runs on AgentFarm, not PAPI. Use the agentfarm.<domain> host with the same JWT you obtained from PAPI (human login, refresh, or a service account token).
PAPI_BASE="https://papi.beta.runwhen.com" # self-hosted: https://papi.<your-domain>AGENTFARM_BASE="https://agentfarm.beta.runwhen.com" # self-hosted: https://agentfarm.<your-domain>WS="my-workspace"TOKEN="<your-access-token>"USER="you@example.com" # must be a valid email — sessions are keyed on userIdThe primary endpoint streams Server-Sent Events (text/event-stream). Each data: line is a JSON object. On the first turn, set sessionId to null; the stream assigns a sessionId you reuse on follow-up turns.
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/workspaces/{workspace}/chat-pro-sse | Start or continue a chat turn (SSE stream) |
POST | /api/v1/workspaces/{workspace}/chat/{sessionId}/abort | Stop an in-flight turn |
POST | /api/v1/workspaces/{workspace}/chat-export-url | Create a read-only export link for a session |
Start a new chat
curl -N -X POST "$AGENTFARM_BASE/api/v1/workspaces/$WS/chat-pro-sse" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: text/event-stream" \ -d '{ "userId": "'"$USER"'", "message": "What issues are open in the payments namespace?", "sessionId": null, "personaName": null }'Watch the stream for frames containing "sessionId" — save that value for the next turn.
Continue a session
SESSION="<session-id-from-first-stream>"
curl -N -X POST "$AGENTFARM_BASE/api/v1/workspaces/$WS/chat-pro-sse" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: text/event-stream" \ -d '{ "userId": "'"$USER"'", "message": "Drill into the highest-severity one.", "sessionId": "'"$SESSION"'" }'Run a slash-command programmatically
Saved workspace Commands (created via the Commands API or Workspace Studio) can be invoked by sending the same markdown link the UI uses. Replace {commandId} with the command’s numeric id from GET .../chat-config/commands:
curl -N -X POST "$AGENTFARM_BASE/api/v1/workspaces/$WS/chat-pro-sse" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "Accept: text/event-stream" \ -d '{ "userId": "'"$USER"'", "message": "[onboard-me](http://chat-command/42)", "sessionId": null }'AgentFarm expands the citation into the command body before the assistant runs the procedure.
Abort and export
# Abort an in-flight turn (202 Accepted)curl -sS -X POST "$AGENTFARM_BASE/api/v1/workspaces/$WS/chat/$SESSION/abort" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"userId": "'"$USER"'"}'
# Share a completed session (returns a relative exportUrl path)curl -sS -X POST "$AGENTFARM_BASE/api/v1/workspaces/$WS/chat-export-url" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"userId": "'"$USER"'", "sessionId": "'"$SESSION"'"}'Open the interactive reference at /api-docs and select the AgentFarm server to explore request/response schemas.