# Logs, alerts and digest An app’s logs and metrics, alert rules and their history, the weekly digest and the public status page. 12 routes, from the API’s own OpenAPI document. URL: https://docs.qaldy.com/reference/api/observe/ 12 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/​apps/​{id}/​logs`](#get-v1-apps-id-logs) | The last log lines of an app (its own output, runs and gate decisions) | | [[GET]] | [`/​v1/​apps/​{id}/​metrics`](#get-v1-apps-id-metrics) | Requests, errors, latency, CPU time and runs of an app, with the period before | | [[GET]] | [`/​v1/​workspaces/​{ws}/​alerts`](#get-v1-workspaces-ws-alerts) | Alert rules, what is firing now and the latest history | | [[GET]] | [`/​v1/​workspaces/​{ws}/​alerts/​history`](#get-v1-workspaces-ws-alerts-history) | Alert history, newest first | | [[POST]] | [`/​v1/​workspaces/​{ws}/​alerts/​rules`](#post-v1-workspaces-ws-alerts-rules) | Add an alert rule | | [[PUT]] | [`/​v1/​workspaces/​{ws}/​alerts/​rules/​{id}`](#put-v1-workspaces-ws-alerts-rules-id) | Replace an alert rule | | [[DELETE]] | [`/​v1/​workspaces/​{ws}/​alerts/​rules/​{id}`](#delete-v1-workspaces-ws-alerts-rules-id) | Remove an alert rule (an alert it had open is closed) | | [[POST]] | [`/​v1/​workspaces/​{ws}/​alerts/​rules/​{id}/​test`](#post-v1-workspaces-ws-alerts-rules-id-test) | Send a test alert through the rule’s channels | | [[GET]] | [`/​v1/​workspaces/​{ws}/​observe/​digest/​preview`](#get-v1-workspaces-ws-observe-digest-preview) | This week’s digest as it would be emailed to you (nothing is sent) | | [[POST]] | [`/​v1/​workspaces/​{ws}/​observe/​digest/​send-test`](#post-v1-workspaces-ws-observe-digest-send-test) | Email this week’s digest to yourself only | | [[GET]] | [`/​v1/​workspaces/​{ws}/​observe/​settings`](#get-v1-workspaces-ws-observe-settings) | The weekly digest and the public status page: switches and who gets what | | [[PATCH]] | [`/​v1/​workspaces/​{ws}/​observe/​settings`](#patch-v1-workspaces-ws-observe-settings) | Switch the digest or the status page on or off; a recipient can unsubscribe themselves | ## Reference ### [[GET]] `/v1/apps/{id}/logs` The last log lines of an app (its own output, runs and gate decisions). - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_edit` on the app; tokens: `read` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | | `level` | query | "debug" · "info" · "warn" · "error" | | | | `q` | query | string | | 1 to 100 characters | | `runId` | query | string | | 1 to 128 characters | | `before` | query | integer | | at least 1 | | `limit` | query | integer | | 1 to 500. default 200 | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `lines` | object[] | yes | | | `lines[].id` | integer | yes | at least 1 | | `lines[].at` | string (date-time) | yes | | | `lines[].appId` | string | yes | at least 1 characters | | `lines[].runId` | string or null | yes | at least 1 characters | | `lines[].level` | "debug" · "info" · "warn" · "error" | yes | | | `lines[].source` | "app" · "platform" · "gate" | yes | | | `lines[].message` | string | yes | up to 2000 characters | | `hasMore` | boolean | yes | | | `keepDays` | integer | yes | at least 1 | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/apps/{id}/metrics` Requests, errors, latency, CPU time and runs of an app, with the period before. - **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: `read` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | | `range` | query | "24h" · "7d" | | default "24h" | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `appId` | string | yes | at least 1 characters | | `range` | "24h" · "7d" | yes | | | `from` | string (date-time) | yes | | | `to` | string (date-time) | yes | | | `bucketMs` | integer | yes | at least 60000 | | `buckets` | object[] | yes | | | `buckets[].at` | string (date-time) | yes | | | `buckets[].requests` | integer | yes | at least 0 | | `buckets[].errors` | integer | yes | at least 0 | | `buckets[].p50Ms` | number or null | yes | at least 0 | | `buckets[].p95Ms` | number or null | yes | at least 0 | | `buckets[].cpuMs` | number or null | yes | at least 0 | | `buckets[].runs` | integer | yes | at least 0 | | `buckets[].failedRuns` | integer | yes | at least 0 | | `totals` | object | yes | | | `totals.requests` | integer | yes | at least 0 | | `totals.errors` | integer | yes | at least 0 | | `totals.errorRate` | number or null | yes | 0 to 1 | | `totals.p50Ms` | number or null | yes | at least 0 | | `totals.p95Ms` | number or null | yes | at least 0 | | `totals.cpuMs` | number or null | yes | at least 0 | | `totals.runs` | integer | yes | at least 0 | | `totals.failedRuns` | integer | yes | at least 0 | | `totals.runP50Ms` | number or null | yes | at least 0 | | `totals.runP95Ms` | number or null | yes | at least 0 | | `previous` | object | yes | | | `previous.requests` | integer | yes | at least 0 | | `previous.errors` | integer | yes | at least 0 | | `previous.errorRate` | number or null | yes | 0 to 1 | | `previous.p50Ms` | 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}/alerts` Alert rules, what is firing now and the latest history. - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `rules` | object[] | yes | | | `open` | object[] | yes | | | `open[].id` | string | yes | at least 1 characters | | `open[].at` | string (date-time) | yes | | | `open[].ruleId` | string or null | yes | | | `open[].kind` | "error_rate" · "quiet" · "budget" · "heartbeat" | yes | | | `open[].state` | "fired" · "resolved" · "test" | yes | | | `open[].appId` | string or null | yes | | | `open[].appName` | string or null | yes | | | `open[].title` | string | yes | 1 to 200 characters | | `open[].detail` | string | yes | up to 600 characters | | `open[].deliveries` | object[] | yes | | | `recent` | object[] | yes | | | `recent[].id` | string | yes | at least 1 characters | | `recent[].at` | string (date-time) | yes | | | `recent[].ruleId` | string or null | yes | | | `recent[].kind` | "error_rate" · "quiet" · "budget" · "heartbeat" | yes | | | `recent[].state` | "fired" · "resolved" · "test" | yes | | | `recent[].appId` | string or null | yes | | | `recent[].appName` | string or null | yes | | | `recent[].title` | string | yes | 1 to 200 characters | | `recent[].detail` | string | yes | up to 600 characters | | `recent[].deliveries` | object[] | yes | | | `channels` | object | yes | | | `channels.telegram` | object[] | yes | | | `channels.emailAvailable` | boolean | yes | | | `channels.emailRecipients` | integer | yes | at least 0 | | `apps` | object[] | yes | | | `apps[].id` | string | yes | at least 1 characters | | `apps[].name` | string | yes | at least 1 characters | …and 1 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}/alerts/history` Alert history, newest first. - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | | `limit` | query | integer | | 1 to 100. default 30 | | `cursor` | query | string | | up to 80 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `events` | object[] | yes | | | `events[].id` | string | yes | at least 1 characters | | `events[].at` | string (date-time) | yes | | | `events[].ruleId` | string or null | yes | | | `events[].kind` | "error_rate" · "quiet" · "budget" · "heartbeat" | yes | | | `events[].state` | "fired" · "resolved" · "test" | yes | | | `events[].appId` | string or null | yes | | | `events[].appName` | string or null | yes | | | `events[].title` | string | yes | 1 to 200 characters | | `events[].detail` | string | yes | up to 600 characters | | `events[].deliveries` | object[] | yes | | | `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)). ### [[POST]] `/v1/workspaces/{ws}/alerts/rules` Add an alert rule. - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) An empty object: `{}`. **Response 200** A object. Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[PUT]] `/v1/workspaces/{ws}/alerts/rules/{id}` Replace an alert rule. - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | | `id` | path | string | yes | 1 to 64 characters | **Request body** (`application/json`) An empty object: `{}`. **Response 200** A object. Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[DELETE]] `/v1/workspaces/{ws}/alerts/rules/{id}` Remove an alert rule (an alert it had open is closed). - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | | `id` | path | string | yes | 1 to 64 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `ok` | true | yes | | 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}/alerts/rules/{id}/test` Send a test alert through the rule’s channels. - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | | `id` | path | string | yes | 1 to 64 characters | **Request body** (`application/json`) An empty object: `{}`. **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `id` | string | yes | at least 1 characters | | `at` | string (date-time) | yes | | | `ruleId` | string or null | yes | | | `kind` | "error_rate" · "quiet" · "budget" · "heartbeat" | yes | | | `state` | "fired" · "resolved" · "test" | yes | | | `appId` | string or null | yes | | | `appName` | string or null | yes | | | `title` | string | yes | 1 to 200 characters | | `detail` | string | yes | up to 600 characters | | `deliveries` | object[] | yes | | | `deliveries[].channel` | "in_app" · "email" · "telegram" | yes | | | `deliveries[].ok` | boolean | yes | | | `deliveries[].reason` | string or null | yes | up to 64 characters | 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}/observe/digest/preview` This week’s digest as it would be emailed to you (nothing is sent). - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `subject` | string | yes | at least 1 characters | | `html` | string | yes | at least 1 characters | | `text` | string | yes | at least 1 characters | | `to` | string | yes | at least 1 characters | | `from` | string (date-time) | yes | | | `until` | string (date-time) | yes | | 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}/observe/digest/send-test` Email this week’s digest to yourself only. - **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:** admin | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) An empty object: `{}`. **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `sent` | boolean | yes | | | `reason` | 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)). ### [[GET]] `/v1/workspaces/{ws}/observe/settings` The weekly digest and the public status page: switches and who gets what. - **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 | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `digest` | object | yes | | | `digest.enabled` | boolean | yes | | | `digest.isRecipient` | boolean | yes | | | `digest.subscribed` | boolean | yes | | | `digest.recipients` | integer | yes | at least 0 | | `digest.lastSentAt` | string (date-time) or null | yes | | | `digest.nextSendAt` | string (date-time) | yes | | | `digest.emailAvailable` | boolean | yes | | | `status` | object | yes | | | `status.settings` | object | yes | | | `status.path` | string | yes | at least 1 characters | | `status.apps` | object[] | yes | | | `canEdit` | boolean | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[PATCH]] `/v1/workspaces/{ws}/observe/settings` Switch the digest or the status page on or off; a recipient can unsubscribe themselves. - **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:** admin; a digest recipient may change their own `subscribed` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `ws` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `digest` | object | | | | `digest.enabled` | boolean | | | | `digest.subscribed` | boolean | | | | `status` | object | | | | `status.enabled` | boolean | | | | `status.title` | string or null | | up to 80 characters | | `status.appIds` | string[] | | up to 50 items | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `digest` | object | yes | | | `digest.enabled` | boolean | yes | | | `digest.isRecipient` | boolean | yes | | | `digest.subscribed` | boolean | yes | | | `digest.recipients` | integer | yes | at least 0 | | `digest.lastSentAt` | string (date-time) or null | yes | | | `digest.nextSendAt` | string (date-time) | yes | | | `digest.emailAvailable` | boolean | yes | | | `status` | object | yes | | | `status.settings` | object | yes | | | `status.path` | string | yes | at least 1 characters | | `status.apps` | object[] | yes | | | `canEdit` | boolean | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)).