# Runs The run list, one run, the plain-words explanation of a failure and the gate’s trace of what a run was allowed to do. 14 routes, from the API’s own OpenAPI document. URL: https://docs.qaldy.com/reference/api/runs/ 14 routes. Every path starts at `https://cloud-api.qaldy.com`. Sign-in, tokens, errors and limits are on the [overview](https://docs.qaldy.com/reference/api/). ## Routes | Method | Path | What it does | |---|---|---| | [[GET]] | [`/​v1/​dead-letters/​{id}`](#get-v1-dead-letters-id) | One dead letter, with the input it kept (for people who may edit the app) | | [[POST]] | [`/​v1/​dead-letters/​{id}/​discard`](#post-v1-dead-letters-id-discard) | Set a dead letter aside: it is kept for a week as a record, then removed | | [[POST]] | [`/​v1/​dead-letters/​{id}/​replay`](#post-v1-dead-letters-id-replay) | Replay a dead letter as a new run, with its input as kept or an edited one | | [[GET]] | [`/​v1/​runs/​{id}`](#get-v1-runs-id) | One run with its step timeline | | [[GET]] | [`/​v1/​runs/​{id}/​ask`](#get-v1-runs-id-ask) | What a run did, why, and what changed since the last good run (rules; free) | | [[POST]] | [`/​v1/​runs/​{id}/​ask`](#post-v1-runs-id-ask) | Ask about this run: a model writes the answer when the workspace has a key for one | | [[POST]] | [`/​v1/​runs/​{id}/​change`](#post-v1-runs-id-change) | Plan the change a refused run suggests (let the app reach the host the gate refused): the diff, nothing built | | [[GET]] | [`/​v1/​runs/​{id}/​explain`](#get-v1-runs-id-explain) | Explain & fix: what happened, why, and the next step | | [[POST]] | [`/​v1/​runs/​{id}/​replay`](#post-v1-runs-id-replay) | Replay a failed run as a new run, optionally with an edited input | | [[GET]] | [`/​v1/​runs/​{id}/​trace`](#get-v1-runs-id-trace) | What the platform recorded around a run: gate decisions and its last log lines | | [[GET]] | [`/​v1/​workspaces/​{ws}/​dead-letters`](#get-v1-workspaces-ws-dead-letters) | Failed runs and refused webhook calls kept for replay (apps you can open) | | [[POST]] | [`/​v1/​workspaces/​{ws}/​dead-letters/​bulk`](#post-v1-workspaces-ws-dead-letters-bulk) | Replay or discard up to 50 open dead letters as they were kept | | [[GET]] | [`/​v1/​workspaces/​{ws}/​queue-health`](#get-v1-workspaces-ws-queue-health) | Work in flight, how long the oldest has waited and what finished (apps you can open) | | [[GET]] | [`/​v1/​workspaces/​{ws}/​runs`](#get-v1-workspaces-ws-runs) | Runs, newest first (only apps you can view) | ## Reference ### [[GET]] `/v1/dead-letters/{id}` One dead letter, with the input it kept (for people who may edit the app). - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view` on the app, else 404 | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `id` | string | yes | at least 1 characters | | `kind` | "run" · "delivery" | yes | | | `state` | "open" · "replayed" · "discarded" | yes | | | `appId` | string | yes | at least 1 characters | | `appName` | string | yes | at least 1 characters | | `roadId` | string or null | yes | | | `roadName` | string or null | yes | | | `trigger` | "schedule" · "webhook" · "form" · "manual" · "event" | yes | | | `reason` | string | yes | at least 1 characters | | `message` | string | yes | at least 1 characters | | `runId` | string or null | yes | | | `deliveryId` | string or null | yes | | | `version` | object or null | yes | | | `version.id` | string | yes | at least 1 characters | | `version.number` | integer or null | yes | at least 1 | | `version.isCurrent` | boolean | yes | | | `attempt` | integer | yes | at least 1 | | `hasPayload` | boolean | yes | | | `payloadBytes` | integer | yes | at least 0 | | `preview` | string or null | yes | | | `createdAt` | string (date-time) | yes | | | `settledAt` | string (date-time) or null | yes | | | `settledByName` | string or null | yes | | | `replayRunId` | string or null | yes | | | `canManage` | boolean | yes | | | `payload` | any or null | | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/dead-letters/{id}/discard` Set a dead letter aside: it is kept for a week as a record, then removed. - **Authentication:** the console’s session cookie. - **Token:** not available. This route is for a signed-in person in the console (`403 console_only` for a token). - **Who:** `can_edit` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) An empty object: `{}`. **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `id` | string | yes | at least 1 characters | | `kind` | "run" · "delivery" | yes | | | `state` | "open" · "replayed" · "discarded" | yes | | | `appId` | string | yes | at least 1 characters | | `appName` | string | yes | at least 1 characters | | `roadId` | string or null | yes | | | `roadName` | string or null | yes | | | `trigger` | "schedule" · "webhook" · "form" · "manual" · "event" | yes | | | `reason` | string | yes | at least 1 characters | | `message` | string | yes | at least 1 characters | | `runId` | string or null | yes | | | `deliveryId` | string or null | yes | | | `version` | object or null | yes | | | `version.id` | string | yes | at least 1 characters | | `version.number` | integer or null | yes | at least 1 | | `version.isCurrent` | boolean | yes | | | `attempt` | integer | yes | at least 1 | | `hasPayload` | boolean | yes | | | `payloadBytes` | integer | yes | at least 0 | | `preview` | string or null | yes | | | `createdAt` | string (date-time) | yes | | | `settledAt` | string (date-time) or null | yes | | | `settledByName` | string or null | yes | | | `replayRunId` | string or null | yes | | | `canManage` | boolean | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/dead-letters/{id}/replay` Replay a dead letter as a new run, with its input as kept or an edited one. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `write` scope. - **Who:** `can_edit` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `payload` | any or null | | | | `version` | "current" · "original" | | default "current" | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `runId` | string | yes | at least 1 characters | | `deadLetterId` | string or null | yes | | | `version` | object | yes | | | `version.id` | string | yes | at least 1 characters | | `version.number` | integer or null | yes | at least 1 | | `version.isCurrent` | boolean | yes | | | `edited` | boolean | yes | | | `held` | boolean | | default false | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/runs/{id}` One run with its step timeline. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view` on the app | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `id` | string | yes | at least 1 characters | | `workspaceId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `appName` | string | yes | at least 1 characters | | `roadId` | string or null | yes | | | `roadName` | string or null | yes | | | `trigger` | "schedule" · "webhook" · "form" · "manual" · "event" | yes | | | `status` | "queued" · "running" · "waiting_approval" · "succeeded" · "failed" · "blocked" | yes | | | `startedAt` | string (date-time) | yes | | | `finishedAt` | string (date-time) or null | yes | | | `durationMs` | integer or null | yes | at least 0 | | `minutesSaved` | number | yes | at least 0 | | `errorCode` | string or null | yes | | | `errorMessage` | string or null | yes | | | `version` | object or null | | | | `version.id` | string | yes | at least 1 characters | | `version.number` | integer or null | yes | at least 1 | | `version.isCurrent` | boolean | yes | | | `replayOf` | string or null | | | | `steps` | object[] | yes | | | `steps[].index` | integer | yes | at least 0 | | `steps[].label` | string | yes | at least 1 characters | | `steps[].at` | object or null | yes | | | `steps[].status` | "pending" · "running" · "ok" · "waiting" · "failed" · "blocked" · "skipped" | yes | | | `steps[].startedAt` | string (date-time) or null | yes | | | `steps[].durationMs` | integer or null | yes | at least 0 | | `steps[].detail` | string or null | yes | | | `explanation` | object or null | yes | | | `explanation.what` | string | yes | at least 1 characters | | `explanation.why` | string | yes | at least 1 characters | …and 4 more fields. The full schema is in [openapi.json](https://docs.qaldy.com/openapi.json). Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/runs/{id}/ask` What a run did, why, and what changed since the last good run (rules; free). - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view` on the app; tokens: yes, read scope | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | | `locale` | query | "en" · "ru" · "kk" | | | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `runId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `appName` | string | yes | at least 1 characters | | `generatedAt` | string (date-time) | yes | | | `locale` | "en" · "ru" · "kk" | yes | | | `source` | "rules" · "workspace_model" · "platform_model" | yes | | | `model` | string or null | yes | | | `cached` | boolean | yes | | | `status` | "queued" · "running" · "waiting_approval" · "succeeded" · "failed" · "blocked" | yes | | | `failureClass` | "egress_denied" · "secret_missing" · "auth_rejected" · "quota" · "ai_budget" · "ai_setup" · "timeout" · "connector_rate_limited" · … or null | yes | | | `confidence` | "high" · "medium" · "low" | yes | | | `headline` | string | yes | 1 to 600 characters | | `why` | string | yes | 1 to 1200 characters | | `next` | string | yes | 1 to 1200 characters | | `answer` | string or null | yes | up to 2400 characters | | `evidence` | string[] | yes | up to 12 items | | `whatChanged` | object | yes | | | `whatChanged.lastGood` | object or null | yes | | | `whatChanged.versionChanged` | boolean or null | yes | | | `whatChanged.codeChanged` | boolean or null | yes | | | `whatChanged.lines` | string[] | yes | up to 12 items | | `fix` | object or null | yes | | | `fix.kind` | "reconnect" · "allow_egress" · "retry" · "edit_app" · "rollback" · "models" · "capacity" | yes | | | `fix.connectorId` | "shop" · "stripe" · "gmail" · "telegram" · "sheets" · "slack" · "kaspi" · "1c" · … | | | | `fix.domain` | string | | 1 to 253 characters | | `fix.versionId` | string | | at least 1 characters | | `fix.versionNumber` | integer | | at least 1 | | `suggestion` | object or null | yes | | | `suggestion.kind` | "allow_egress" | yes | | | `suggestion.domain` | string | yes | 1 to 253 characters | …and 6 more fields. The full schema is in [openapi.json](https://docs.qaldy.com/openapi.json). Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/runs/{id}/ask` Ask about this run: a model writes the answer when the workspace has a key for one. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view`; a model answer needs `can_edit`; tokens: yes, read scope | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `question` | string | | 2 to 500 characters | | `locale` | "en" · "ru" · "kk" | | | | `rulesOnly` | boolean | | | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `runId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `appName` | string | yes | at least 1 characters | | `generatedAt` | string (date-time) | yes | | | `locale` | "en" · "ru" · "kk" | yes | | | `source` | "rules" · "workspace_model" · "platform_model" | yes | | | `model` | string or null | yes | | | `cached` | boolean | yes | | | `status` | "queued" · "running" · "waiting_approval" · "succeeded" · "failed" · "blocked" | yes | | | `failureClass` | "egress_denied" · "secret_missing" · "auth_rejected" · "quota" · "ai_budget" · "ai_setup" · "timeout" · "connector_rate_limited" · … or null | yes | | | `confidence` | "high" · "medium" · "low" | yes | | | `headline` | string | yes | 1 to 600 characters | | `why` | string | yes | 1 to 1200 characters | | `next` | string | yes | 1 to 1200 characters | | `answer` | string or null | yes | up to 2400 characters | | `evidence` | string[] | yes | up to 12 items | | `whatChanged` | object | yes | | | `whatChanged.lastGood` | object or null | yes | | | `whatChanged.versionChanged` | boolean or null | yes | | | `whatChanged.codeChanged` | boolean or null | yes | | | `whatChanged.lines` | string[] | yes | up to 12 items | | `fix` | object or null | yes | | | `fix.kind` | "reconnect" · "allow_egress" · "retry" · "edit_app" · "rollback" · "models" · "capacity" | yes | | | `fix.connectorId` | "shop" · "stripe" · "gmail" · "telegram" · "sheets" · "slack" · "kaspi" · "1c" · … | | | | `fix.domain` | string | | 1 to 253 characters | | `fix.versionId` | string | | at least 1 characters | | `fix.versionNumber` | integer | | at least 1 | | `suggestion` | object or null | yes | | | `suggestion.kind` | "allow_egress" | yes | | | `suggestion.domain` | string | yes | 1 to 253 characters | …and 6 more fields. The full schema is in [openapi.json](https://docs.qaldy.com/openapi.json). Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/runs/{id}/change` Plan the change a refused run suggests (let the app reach the host the gate refused): the diff, nothing built. - **Authentication:** the console’s session cookie. - **Token:** not available. This route is for a signed-in person in the console (`403 console_only` for a token). - **Who:** `can_edit` and a builder; console only (tokens: no) | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) An empty object: `{}`. **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `changeId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `appName` | string | yes | at least 1 characters | | `baseVersionId` | string | yes | at least 1 characters | | `instruction` | string | yes | | | `summary` | string | yes | 1 to 300 characters | | `manifest` | object | yes | | | `manifest.name` | string | yes | 2 to 60 characters | | `manifest.description` | string | yes | 4 to 280 characters | | `manifest.archetype` | "kiosk" · "tower" · "warehouse" · "workshop" · "bank" · "townhall" · "clocktower" · "printhouse" · … | yes | | | `manifest.category` | "interface" · "data" · "messaging" · "money" · "ai" · "time" · "people" · "growth" | yes | | | `manifest.permissions` | object | yes | | | `manifest.triggers` | object[] | yes | | | `manifest.sharing` | object | yes | | | `manifest.roi` | object | yes | | | `diff` | object | yes | | | `diff.gains` | object[] | yes | | | `diff.losses` | object[] | yes | | | `diff.triggersAdded` | object[] | yes | | | `diff.triggersRemoved` | object[] | yes | | | `diff.details` | object[] | yes | | | `steps` | string[] | yes | | | `rebuildsCode` | boolean | yes | | | `builder` | "claude" · "offline" | yes | | | `model` | string or null | yes | | | `templateId` | string or null | yes | | | `notes` | string[] | yes | up to 8 items | | `adminApproval` | object | yes | | | `adminApproval.required` | boolean | yes | | | `adminApproval.connectors` | string[] | yes | | …and 2 more fields. The full schema is in [openapi.json](https://docs.qaldy.com/openapi.json). Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/runs/{id}/explain` Explain & fix: what happened, why, and the next step. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view` on the app | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `what` | string | yes | at least 1 characters | | `why` | string | yes | at least 1 characters | | `next` | string | yes | at least 1 characters | | `fix` | object or null | yes | | | `fix.kind` | "reconnect" · "allow-domain" · "retry" · "edit-app" | yes | | | `fix.label` | string | yes | at least 1 characters | | `fix.connectorId` | "shop" · "stripe" · "gmail" · "telegram" · "sheets" · "slack" · "kaspi" · "1c" · … | | | | `fix.domain` | string | | | | `nothingLost` | boolean | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/runs/{id}/replay` Replay a failed run as a new run, optionally with an edited input. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `write` scope. - **Who:** `can_edit` on the app; over a token, `version: original` is refused with `approval_needs_console` when that version may do more than the app does now | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `payload` | any or null | | | | `version` | "current" · "original" | | default "current" | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `runId` | string | yes | at least 1 characters | | `deadLetterId` | string or null | yes | | | `version` | object | yes | | | `version.id` | string | yes | at least 1 characters | | `version.number` | integer or null | yes | at least 1 | | `version.isCurrent` | boolean | yes | | | `edited` | boolean | yes | | | `held` | boolean | | default false | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/runs/{id}/trace` What the platform recorded around a run: gate decisions and its last log lines. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view` on the app | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | | `limit` | query | integer | | 1 to 50. default 20 | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `runId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `gate` | object[] | yes | | | `gate[].at` | string (date-time) | yes | | | `gate[].kind` | "egress.allowed" · "egress.blocked" · "connector.called" · "flow.blocked" · "flow.allowed" | yes | | | `gate[].domain` | string | yes | at least 1 characters | | `gate[].method` | string | yes | at least 1 characters | | `gate[].status` | integer | yes | at least 0 | | `gate[].reason` | string or null | yes | | | `gate[].connector` | string or null | yes | | | `gate[].action` | string or null | yes | | | `gate[].labels` | string[] | | up to 8 items | | `log` | object[] | yes | | | `log[].at` | string (date-time) | yes | | | `log[].level` | "info" · "warn" · "error" | yes | | | `log[].source` | "run" · "step" · "gate" | yes | | | `log[].text` | string | yes | | | `logSource` | "platform" | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/workspaces/{ws}/dead-letters` Failed runs and refused webhook calls kept for replay (apps you can open). - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** member (filtered to `can_view`) | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | | `state` | query | "open" · "replayed" · "discarded" · "all" | | default "open" | | `appId` | query | string | | 1 to 128 characters | | `automationId` | query | string | | 1 to 128 characters | | `runId` | query | string | | 1 to 128 characters | | `kind` | query | "run" · "delivery" | | | | `limit` | query | integer | | 1 to 100. default 50 | | `cursor` | query | string | | up to 200 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `items` | object[] | yes | | | `items[].id` | string | yes | at least 1 characters | | `items[].kind` | "run" · "delivery" | yes | | | `items[].state` | "open" · "replayed" · "discarded" | yes | | | `items[].appId` | string | yes | at least 1 characters | | `items[].appName` | string | yes | at least 1 characters | | `items[].roadId` | string or null | yes | | | `items[].roadName` | string or null | yes | | | `items[].trigger` | "schedule" · "webhook" · "form" · "manual" · "event" | yes | | | `items[].reason` | string | yes | at least 1 characters | | `items[].message` | string | yes | at least 1 characters | | `items[].runId` | string or null | yes | | | `items[].deliveryId` | string or null | yes | | | `items[].version` | object or null | yes | | | `items[].attempt` | integer | yes | at least 1 | | `items[].hasPayload` | boolean | yes | | | `items[].payloadBytes` | integer | yes | at least 0 | | `items[].preview` | string or null | yes | | | `items[].createdAt` | string (date-time) | yes | | | `items[].settledAt` | string (date-time) or null | yes | | | `items[].settledByName` | string or null | yes | | | `items[].replayRunId` | string or null | yes | | | `items[].canManage` | boolean | yes | | | `nextCursor` | string or null | yes | | | `counts` | object | yes | | | `counts.open` | integer | yes | at least 0 | | `counts.replayed` | integer | yes | at least 0 | | `counts.discarded` | integer | yes | at least 0 | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/workspaces/{ws}/dead-letters/bulk` Replay or discard up to 50 open dead letters as they were kept. - **Authentication:** the console’s session cookie. - **Token:** not available. This route is for a signed-in person in the console (`403 console_only` for a token). - **Who:** member; `can_edit` per app | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `action` | "replay" · "discard" | yes | | | `ids` | string[] | yes | up to 50 items | | `version` | "current" · "original" | | default "current" | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `action` | "replay" · "discard" | yes | | | `results` | object[] | yes | | | `done` | integer | yes | at least 0 | | `failed` | integer | yes | at least 0 | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/workspaces/{ws}/queue-health` Work in flight, how long the oldest has waited and what finished (apps you can open). - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** member (filtered to `can_view`) | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | | `appId` | query | string | | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `asOf` | string (date-time) | yes | | | `totals` | object | yes | | | `totals.waiting` | integer | yes | at least 0 | | `totals.running` | integer | yes | at least 0 | | `totals.awaitingApproval` | integer | yes | at least 0 | | `totals.held` | integer | | at least 0. default 0 | | `totals.oldestSeconds` | integer or null | yes | at least 0 | | `totals.startedLastHour` | integer | yes | at least 0 | | `totals.finishedLastHour` | integer | yes | at least 0 | | `totals.failedLastHour` | integer | yes | at least 0 | | `totals.medianWaitSeconds` | number or null | yes | at least 0 | | `totals.deadLetters` | integer | yes | at least 0 | | `totals.state` | "clear" · "busy" · "slow" · "stuck" | yes | | | `hours` | object[] | yes | | | `hours[].at` | string (date-time) | yes | | | `hours[].started` | integer | yes | at least 0 | | `hours[].finished` | integer | yes | at least 0 | | `hours[].failed` | integer | yes | at least 0 | | `hours[].peak` | integer | yes | at least 0 | | `hours[].medianWaitSeconds` | number or null | yes | at least 0 | | `roads` | object[] | yes | | | `roads[].waiting` | integer | yes | at least 0 | | `roads[].running` | integer | yes | at least 0 | | `roads[].awaitingApproval` | integer | yes | at least 0 | | `roads[].held` | integer | | at least 0. default 0 | | `roads[].oldestSeconds` | integer or null | yes | at least 0 | | `roads[].startedLastHour` | integer | yes | at least 0 | | `roads[].finishedLastHour` | integer | yes | at least 0 | | `roads[].failedLastHour` | integer | yes | at least 0 | | `roads[].medianWaitSeconds` | number or null | yes | at least 0 | …and 7 more fields. The full schema is in [openapi.json](https://docs.qaldy.com/openapi.json). Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/workspaces/{ws}/runs` Runs, newest first (only apps you can view). - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** member (filtered to `can_view`) | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | | `status` | query | "queued" · "running" · "waiting_approval" · "succeeded" · "failed" · "blocked"[] | | | | `appId` | query | string | | at least 1 characters | | `trigger` | query | "schedule" · "webhook" · "form" · "manual" · "event" | | | | `limit` | query | integer | | 1 to 200. default 50 | | `cursor` | query | string | | up to 200 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `items` | object[] | yes | | | `items[].id` | string | yes | at least 1 characters | | `items[].workspaceId` | string | yes | at least 1 characters | | `items[].appId` | string | yes | at least 1 characters | | `items[].appName` | string | yes | at least 1 characters | | `items[].roadId` | string or null | yes | | | `items[].roadName` | string or null | yes | | | `items[].trigger` | "schedule" · "webhook" · "form" · "manual" · "event" | yes | | | `items[].status` | "queued" · "running" · "waiting_approval" · "succeeded" · "failed" · "blocked" | yes | | | `items[].startedAt` | string (date-time) | yes | | | `items[].finishedAt` | string (date-time) or null | yes | | | `items[].durationMs` | integer or null | yes | at least 0 | | `items[].minutesSaved` | number | yes | at least 0 | | `items[].errorCode` | string or null | yes | | | `items[].errorMessage` | string or null | yes | | | `items[].version` | object or null | | | | `items[].replayOf` | string or null | | | | `nextCursor` | string or null | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)).