Actions
This page covers the HTTP endpoints you can use to inspect subscription delivery runs, inspect attempt history, read repo-scoped action notifications, and post callback status updates from your webhook handler.
To create, update, pause, or remove subscriptions, use the CLI and MCP workflows or the SDK client.subscription surface. Subscription management REST endpoints under /api/repos/:orgName/:repoName/subs are not currently available.
Reader-relative history visibility
Section titled “Reader-relative history visibility”Accessing action history requires a token with repo:configure scope. repo:configure is the admission gate for these routes — callers without it receive an opaque 404. Whether the caller also holds effective repo:read access determines what appears inside each run row. A narrowed token is one created with allowedMatches patterns that restrict which refs it can read — see token scopes for how those patterns are declared and enforced.
- With unrestricted
repo:read: Run rows include the fullmatchedOperationIndexesarray and free-form diagnostics. On run rows that means the error message; response snippets are carried on attempt rows and in the live feed, not on run rows. - With narrowed
repo:read(scoped PAT withallowedMatches): Run rows are still returned — with statuses, counts, and timestamps — butmatchedOperationIndexesis filtered down to only the operations the caller can read, and free-form diagnostics are stripped. - Without
repo:read: Run rows are still returned — with statuses, counts, and timestamps — butmatchedOperationIndexesis emptied and free-form diagnostics are stripped.
Pagination metadata (such as nextCursor) is part of the page envelope, not the individual run rows, and is unaffected by read-scope narrowing.
GET /api/repos/:orgName/:repoName/actions/runs
Section titled “GET /api/repos/:orgName/:repoName/actions/runs”List action runs for a repository, optionally filtered by subscription name, status, outcome, or exact run ID.
Auth: Required — repo:configure scope. Anonymous callers, under-scoped tokens, and missing repositories all return an opaque 404 with a Vary: Authorization response header so existence is not disclosed; authenticate with repo:configure to see real responses.
Scoped PAT filtering: If your token is a scoped PAT, the list is automatically filtered to runs belonging to subscriptions whose Subscription/<name> refs fall within the PAT’s allowed matches. Runs outside that scope are not returned — you will not receive an error, just a narrower result set. A run lookup for an out-of-scope run follows the same opaque 404 path as an unauthenticated request.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
subscriptionName | string | No | Filter by subscription name |
runId | UUID string | No | Exact-match filter that limits results to at most one run. Must be a UUID-formatted action run identifier — non-UUID values are rejected with 400 VALIDATION_ERROR. All other filters (subscriptionName, status, outcome, since, cursor) remain active and can still narrow the result when runId is present. |
status | enum | No | Filter by status. Must be one of pending, running, processing, retry_wait, succeeded, failed_terminal, dead_letter, or suppressed. Any other value returns 400 VALIDATION_ERROR. Cannot be combined with outcome. |
outcome | enum | No | Filter by outcome. Must be one of succeeded or failed. failed is a coarse filter that matches both failed_terminal and dead_letter runs — there is no literal run status named failed. Any other value returns 400 VALIDATION_ERROR. Cannot be combined with status. |
cursor | string | No | Pagination cursor returned as nextCursor in a previous response. Cannot be combined with since. |
since | integer | No | Runs created after this epoch-milliseconds timestamp. Cannot be combined with cursor. |
limit | integer | No | Maximum runs to return per page. Capped at 200 — values above 200 are rejected with a validation error. |
Passing both status and outcome together, or both since and cursor together, returns 400 VALIDATION_ERROR. These mutual-exclusion rules apply regardless of whether runId is also present — for example, ?runId=...&status=failed_terminal&outcome=failed is still rejected, and ?runId=...&since=...&cursor=... is still rejected.
Response 200
Section titled “Response 200”The response is a page envelope. Use nextCursor in a subsequent request to retrieve the next page; when nextCursor is absent, you have reached the last page.
{ "items": [ { "subscriptionName": "signal-hook", "runId": "019d90f0-1111-7000-8000-000000000001", "status": "succeeded", "matchedOperationIndexes": [0, 1], "attemptCount": 1, "maxAttempts": 5, "createdAt": 1741132800000, "updatedAt": 1741132801000 } ], "nextCursor": "opaque-cursor-string"}Failed runs include lastErrorCode; lastErrorMessage is available only to effective full-repository readers.
Example
Section titled “Example”curl -H "Authorization: Bearer $WH_TOKEN" \ "https://api.warmhub.ai/api/repos/myorg/myrepo/actions/runs?status=failed_terminal"To fetch one exact run by ID:
curl -H "Authorization: Bearer $WH_TOKEN" \ "https://api.warmhub.ai/api/repos/myorg/myrepo/actions/runs?runId=019d90f0-1111-7000-8000-000000000001"To page through results, pass the nextCursor value from each response as the cursor parameter on the next request:
curl -H "Authorization: Bearer $WH_TOKEN" \ "https://api.warmhub.ai/api/repos/myorg/myrepo/actions/runs?cursor=opaque-cursor-string"GET /api/repos/:orgName/:repoName/actions/runs/:runId/attempts
Section titled “GET /api/repos/:orgName/:repoName/actions/runs/:runId/attempts”Get the attempt history for a specific action run.
Auth: Required — repo:configure scope. Anonymous callers, under-scoped tokens, and missing repositories all return an opaque 404 with a Vary: Authorization response header so existence is not disclosed. Authenticated callers with access receive a structured 404 when the requested run does not exist.
Scoped PAT filtering: If your token is a scoped PAT, a run whose Subscription/<name> ref falls outside the PAT’s allowed matches is treated as not found and returns the same opaque 404 as an unauthenticated request.
Path Parameters
Section titled “Path Parameters”| Parameter | Type | Description |
|---|---|---|
runId | string | Action run identifier |
Example
Section titled “Example”curl -H "Authorization: Bearer $WH_TOKEN" \ "https://api.warmhub.ai/api/repos/myorg/myrepo/actions/runs/019d90f0-1111-7000-8000-000000000001/attempts"GET /api/repos/:orgName/:repoName/actions/notifications
Section titled “GET /api/repos/:orgName/:repoName/actions/notifications”List repo-scoped action notification records.
Auth: Required — repo:configure scope. Anonymous callers, under-scoped tokens, and missing repositories all return an opaque 404 with a Vary: Authorization response header so existence is not disclosed; authenticate with repo:configure to see real responses.
Scoped PAT filtering: If your token is a scoped PAT, notifications are filtered to those whose Subscription/<name> refs fall within the PAT’s allowed matches. Notifications outside that scope are silently excluded from the result set.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
since | integer | No | Notifications after this epoch-milliseconds timestamp |
limit | integer | No | Maximum notifications to return. Capped at 200 — values above 200 are rejected with a validation error. |
Example
Section titled “Example”curl -H "Authorization: Bearer $WH_TOKEN" \ "https://api.warmhub.ai/api/repos/myorg/myrepo/actions/notifications?limit=20"POST /api/action-runs/:runId/callback
Section titled “POST /api/action-runs/:runId/callback”Report progress or completion for an asynchronous action run. This endpoint is not repo-prefixed.
In practice, runId comes from the original webhook payload, and most handlers can use the provided callback_url directly instead of constructing the path themselves. See Webhook Payload.
Auth: Required. The required scope depends on whether the callback is for a repo-scoped or org-scoped action:
- Repo-scoped callbacks: Authorize with
repo:action-callback. Tokens withrepo:writeare also accepted. - Org-scoped callbacks: Authorize with
org:action-callback.
Use the narrowest applicable scope (repo:action-callback or org:action-callback) rather than a broader write token.
Body Fields
Section titled “Body Fields”| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | One of processing, success, failure, or retry_requested |
message | string | No | Optional status detail or response snippet |
error | string | No | Optional human-readable error message |
Callback statuses are input commands: processing maps to stored run status processing, success maps to succeeded, failure maps to dead_letter, and retry_requested maps to retry_wait. The success response body includes the actual stored runStatus after the transition.
Example
Section titled “Example”curl -X POST "https://api.warmhub.ai/api/action-runs/${RUN_ID}/callback" \ -H "Authorization: Bearer ${WH_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "status": "failure", "error": "Unexpected field \'category\' on line 5." }'