Skip to content

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.

Open Interactive API Reference →


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.comhttps://papi.beta.runwhen.com
Self-hostedyour global.domain Helm valuehttps://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 the domain server variable; in the examples below, set the BASE/RW_BASE variable accordingly.

Wrong host = 404. Requests to the app. host (e.g. https://app.beta.runwhen.com/api/v3/…) return 404 for every endpoint — that host serves the web UI, not the API. Use papi.<domain>.

Authentication

The RunWhen API authenticates requests using JSON Web Tokens (JWT). To get started:

  1. 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.
  2. Include the token in the Authorization header of every request:
Authorization: Bearer <your-access-token>
  1. 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:

MethodPathPurpose
GET/api/v3/workspaces/{workspace}/service-account-tokensList tokens for this workspace
POST/api/v3/workspaces/{workspace}/service-account-tokensCreate 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}/revokeRevoke 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}/scopesReplace 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 via POST /api/v3/workspaces/{workspace}/reset-service-account and exchanged for a JWT at POST /api/v3/token/. The endpoints above create named API tokens with an explicit role and expiry for the workspace in the path.

Example create:

Terminal window
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 provides semantic, vector-based search for finding the most relevant troubleshooting tasks and CodeBundles based on a natural language description of the problem.


Conventions

ConventionDetails
Content-Typeapplication/json for all request and response bodies
Field namingcamelCase (e.g., slxName, createdAt, runSession)
TimestampsISO 8601 with timezone (e.g., 2026-03-01T12:00:00Z)
IdentifiersInteger primary keys
PaginationList responses use a standard envelope: { count, next, previous, results }
Page navigationUse the page query parameter (some endpoints also support page-size)

Status Codes

CodeMeaning
200 OKRequest succeeded
201 CreatedResource created successfully
204 No ContentResource deleted successfully
400 Bad RequestInvalid request body or parameters
401 UnauthorizedMissing or invalid authentication token
403 ForbiddenInsufficient permissions for the requested resource
404 Not FoundResource does not exist
429 Too Many RequestsRate limit exceeded — implement exponential backoff
500 Internal Server ErrorServer-side error

API Reference

Detailed endpoint documentation is organized by resource. Select a topic below to view available operations, parameters, and example responses.

ResourceDescription
WorkspacesRetrieve and manage workspaces, configuration uploads, health, and status
SLXs, SLIs, SLOs & RunbooksQuery observability primitives — expectations, indicators, objectives, and runbook definitions
RunSessions & RunRequestsCreate diagnostic sessions, execute runbook tasks, and track execution status
IssuesView, update, and analyze detected issues with AI-powered JIT summaries
Workflows & PersonasManage automation workflows, trigger execution, and configure AI personas
CodeCollections & CodeBundlesBrowse code repositories, branches, CodeBundle metadata, and statistics
UsersUser profiles, search, activity feeds, and workspace membership
Task Search & ActivitiesSemantic task search and workspace activity tracking
Operational ContextKnowledge Base notes, chat Rules, chat Commands, and Assistants — the programmatic equivalent of the Building Operational Context guide
Custom Tasks & Tool BuilderAuthor/test task scripts on a runner and commit them as SLXs
Service Account TokensAdmin-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):

Terminal window
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/v4 path prefix. Field names are camelCase.

CRUD

Workspace member access. Note noteId values are UUIDs.

MethodPathPurpose
GET/api/v4/workspaces/{workspace}/notesList notes (`view=full
POST/api/v4/workspaces/{workspace}/notesCreate 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:

Terminal window
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):

Terminal window
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.

MethodPathPurpose
POST/api/v4/workspaces/{workspace}/notes/syncUpsert 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}/notesDelete a batch of notes from one source by sourceIds. dryRun=true previews without deleting. Returns per-sourceId results (deleted/not_found).
Terminal window
# 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.

MethodPathPurpose
GET/api/v4/workspaces/{workspace}/resource-pathsList the workspace’s valid resource paths
GET/api/v4/workspaces/{workspace}/tagsList 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).

MethodPathPurpose
GET/api/v3/workspaces/{workspace}/chat-config/rulesList rules (filter by scope_type, scope_id, is_active)
POST/api/v3/workspaces/{workspace}/chat-config/rulesCreate 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/resolvedResolved rules + commands an assistant will load (optional persona_name)

Rule and Command bodies use snake_case fields. Example create:

Terminal window
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.

MethodPathPurpose
GET/api/v3/workspaces/{workspace}/chat-config/commandsList commands
POST/api/v3/workspaces/{workspace}/chat-config/commandsCreate 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-nowTrigger a scheduled command immediately

Scope types

Rules and Commands are scoped. Both workspace- and persona-level context are always loaded for matching assistants.

Scopescope_typescope_idWho can write
Workspaceworkspace(ignored — derived from URL)Workspace admin
Assistant / personapersonaPersona short nameWorkspace admin
Useruser(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.

MethodPathPurpose
GET/api/v4/workspaces/{workspace}/personasList assistants
GET/api/v4/workspaces/{workspace}/personas/{personaShortName}Get an assistant
POST/api/v4/workspaces/{workspace}/personas/sync-typedCreate 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:

Terminal window
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_scriptrun_script_and_waitcommit_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:

MethodPathPurpose
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}/runbookGet 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:

MethodPathPurpose
POST/api/v1/workspaces/{workspace}/slxs/syncCreate or update an SLX
POST/api/v1/workspaces/{workspace}/runbooks/syncCreate or update the SLX’s Runbook (tasks)
POST/api/v1/workspaces/{workspace}/slis/syncCreate 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/sync upserts the SLX straight into the platform (changes apply immediately). The task code lives in a codebundle Git repo referenced by code_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.

MethodPathPurpose
POST/api/v3/workspaces/{workspace}/author/runRun a task/SLI script on a runner (returns run_id)
GET/api/v3/workspaces/{workspace}/author/run/{runId}/statusPoll run status (RUNNING, SUCCEEDED, FAILED)
GET/api/v3/workspaces/{workspace}/author/run/{runId}/outputParsed output — issues, stdout, stderr, report

Workspace Configuration (supporting reads)

Discovery endpoints used when authoring tasks or building context:

MethodPathPurpose
GET/api/v3/workspaces/{workspace}/secrets-keysList secret key names (not values) for secretVars mapping
GET/api/v3/workspaces/{workspace}/runnersList 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-indexFull config overview — resources, SLXs, and relationships
POST/api/v3/workspaces/{workspace}/autocompleteLightweight 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).

Terminal window
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 userId

The 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.

MethodPathPurpose
POST/api/v1/workspaces/{workspace}/chat-pro-sseStart or continue a chat turn (SSE stream)
POST/api/v1/workspaces/{workspace}/chat/{sessionId}/abortStop an in-flight turn
POST/api/v1/workspaces/{workspace}/chat-export-urlCreate a read-only export link for a session

Start a new chat

Terminal window
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

Terminal window
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:

Terminal window
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

Terminal window
# 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.