From dc0016169fd7543f504dca3cbb3afe00edd66c8d Mon Sep 17 00:00:00 2001 From: flashduty-bot Date: Mon, 19 Oct 2026 08:08:21 +0000 Subject: [PATCH 1/2] docs(api-reference): document the RUM custom dashboard endpoints Add the nine app_key-callable /rum/dashboard/* operations generated from fc-rum main (cmd/server/controller/dashboard + types/dashboard), and reconcile the RUM nav group and both API catalogs. --- api-reference/openapi.en.json | 17962 +++++++++++++++++----------- api-reference/openapi.zh.json | 11260 +++++++++++------ api-reference/rum.openapi.en.json | 5000 +++++++- api-reference/rum.openapi.zh.json | 5004 +++++++- docs.json | 30 + en/openapi/api-catalog.mdx | 20 +- zh/openapi/api-catalog.mdx | 20 +- 7 files changed, 27429 insertions(+), 11867 deletions(-) diff --git a/api-reference/openapi.en.json b/api-reference/openapi.en.json index 6d90bfcb..d7fd1a96 100644 --- a/api-reference/openapi.en.json +++ b/api-reference/openapi.en.json @@ -34535,46 +34535,2751 @@ "required": [ "items" ] + }, + "RumDashboardActor": { + "description": "Person who created or last changed the dashboard or a revision.", + "properties": { + "id": { + "description": "Person ID.", + "format": "int64", + "type": "integer" + }, + "name": { + "description": "Person name.", + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "RumDashboardBarViz": { + "description": "Category bars built from grouped series.", + "properties": { + "kind": { + "description": "Panel kind.", + "enum": [ + "bar" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Bar options passed through to the browser renderer.", + "type": "object" + }, + "unit": { + "description": "Display unit of the panel value. One of `unitless`, `ratio`, `percent`, `milliseconds`, `seconds`, `bytes`, `bits`, `count_per_second`, `bytes_per_second`, `bits_per_second`.", + "enum": [ + "unitless", + "ratio", + "percent", + "milliseconds", + "seconds", + "bytes", + "bits", + "count_per_second", + "bytes_per_second", + "bits_per_second" + ], + "type": "string" + }, + "decimals": { + "description": "Number of decimal places to show.", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "category_field": { + "description": "Field key that supplies the category axis.", + "type": "string" + }, + "value_fields": { + "description": "Field keys plotted as bars.", + "items": { + "description": "Field key.", + "type": "string" + }, + "type": "array" + }, + "data_link": { + "$ref": "#/components/schemas/RumDashboardDataLink" + } + }, + "required": [ + "kind", + "options", + "category_field", + "value_fields" + ], + "type": "object" + }, + "RumDashboardCandidate": { + "description": "One option of a custom variable.", + "properties": { + "text": { + "description": "Label shown in the variable bar. Defaults to `value` when empty.", + "type": "string" + }, + "value": { + "description": "Value substituted into the query.", + "type": "string" + } + }, + "required": [ + "text", + "value" + ], + "type": "object" + }, + "RumDashboardColumnOption": { + "description": "Per-column presentation of a table panel.", + "properties": { + "display_name": { + "description": "Column header. Defaults to the field key when empty.", + "type": "string" + }, + "hidden": { + "description": "Whether the column is hidden. `false` hides nothing; omit to inherit.", + "type": [ + "boolean", + "null" + ] + }, + "width_px": { + "description": "Column width in pixels.", + "type": [ + "integer", + "null" + ] + }, + "unit": { + "description": "Display unit of the panel value. One of `unitless`, `ratio`, `percent`, `milliseconds`, `seconds`, `bytes`, `bits`, `count_per_second`, `bytes_per_second`, `bits_per_second`.", + "enum": [ + "unitless", + "ratio", + "percent", + "milliseconds", + "seconds", + "bytes", + "bits", + "count_per_second", + "bytes_per_second", + "bits_per_second" + ], + "type": "string" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "threshold_display": { + "description": "How the threshold is drawn: `text` colours the value, `background` colours the cell.", + "enum": [ + "text", + "background" + ], + "type": "string" + }, + "data_link": { + "$ref": "#/components/schemas/RumDashboardDataLink" + } + }, + "type": "object" + }, + "RumDashboardCreateRequest": { + "description": "Create request. The caller supplies the dashboard ID, so a retry with the same ID is rejected as a conflict instead of creating a duplicate.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID to create, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "schema_version": { + "description": "Wire schema of the definition. Must be `dashboard.v1`.", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "definition" + ], + "type": "object" + }, + "RumDashboardCustomVariable": { + "description": "Variable whose options are a fixed list.", + "properties": { + "kind": { + "description": "Variable kind.", + "enum": [ + "custom" + ], + "type": "string" + }, + "name": { + "description": "Variable name, referenced as `${name}` in panel queries. 1–64 characters starting with a letter or underscore.", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + }, + "label": { + "description": "Label shown in the variable bar. Defaults to `name` when empty.", + "type": "string" + }, + "selection": { + "$ref": "#/components/schemas/RumDashboardSelectionConfig" + }, + "options": { + "description": "Fixed list of options, 1–1000 entries with unique `value`s.", + "items": { + "$ref": "#/components/schemas/RumDashboardCandidate" + }, + "type": "array" + }, + "default": { + "$ref": "#/components/schemas/RumDashboardSelection" + } + }, + "required": [ + "kind", + "name", + "selection", + "options" + ], + "type": "object" + }, + "RumDashboardDataLink": { + "description": "Link from a panel cell to another dashboard.", + "properties": { + "dashboard_id": { + "description": "Target dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "target_id": { + "description": "Target tab or panel ID inside the dashboard, a canonical UUIDv7 when set.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "pass_time": { + "description": "Whether the current time range is forwarded.", + "type": "boolean" + }, + "variable_mappings": { + "additionalProperties": { + "$ref": "#/components/schemas/RumDashboardLinkMapping" + }, + "description": "Target variable name to its mapping. At most 5 links are allowed per panel.", + "type": "object" + } + }, + "required": [ + "dashboard_id", + "pass_time", + "variable_mappings" + ], + "type": "object" + }, + "RumDashboardDatasourceRef": { + "description": "Datasource a panel or query variable reads. RUM dashboards only read the built-in RUM datasource, so the reference is always fixed.", + "properties": { + "kind": { + "description": "Reference kind. Always `fixed`.", + "enum": [ + "fixed" + ], + "type": "string" + }, + "datasource_type": { + "description": "Datasource type. Always `rum`.", + "enum": [ + "rum" + ], + "type": "string" + }, + "datasource_id": { + "description": "Reserved, and always `0` for the built-in RUM datasource.", + "enum": [ + 0 + ], + "type": "integer" + } + }, + "required": [ + "kind", + "datasource_type" + ], + "type": "object" + }, + "RumDashboardDefinition": { + "description": "The dashboard body: title, default time range, variables, and tabs. A dashboard is capped at 10 tabs, 100 panels and 300 queries.", + "properties": { + "title": { + "description": "Dashboard title, 1–189 characters.", + "type": "string" + }, + "description": { + "description": "Dashboard description, at most 1024 characters.", + "maxLength": 1024, + "type": "string" + }, + "default_time_range": { + "$ref": "#/components/schemas/RumDashboardRelativeTimeRange" + }, + "refresh_interval": { + "description": "Auto-refresh interval of the dashboard. One of `off`, `30s`, `1m`, `5m`.", + "enum": [ + "off", + "30s", + "1m", + "5m" + ], + "type": "string" + }, + "variables": { + "description": "Variable bar entries, at most 20. The built-in `app` switch is not declared here.", + "items": { + "$ref": "#/components/schemas/RumDashboardVariable" + }, + "maxItems": 20, + "type": "array" + }, + "tabs": { + "description": "Tabs of the dashboard, 1–10.", + "items": { + "$ref": "#/components/schemas/RumDashboardTab" + }, + "maxItems": 10, + "type": "array" + } + }, + "required": [ + "title", + "default_time_range", + "refresh_interval", + "variables", + "tabs" + ], + "type": "object" + }, + "RumDashboardDeleteResponse": { + "description": "Result of moving a dashboard to the trash.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "revision": { + "description": "Revision the dashboard was at when deleted.", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "revision" + ], + "type": "object" + }, + "RumDashboardFieldSort": { + "description": "Sort order of a table column.", + "properties": { + "field": { + "description": "Field key to sort by.", + "type": "string" + }, + "direction": { + "description": "Sort direction: `asc` or `desc`.", + "enum": [ + "asc", + "desc" + ], + "type": "string" + } + }, + "required": [ + "field", + "direction" + ], + "type": "object" + }, + "RumDashboardGridPosition": { + "description": "Panel position on the tab's 24-column grid. `x + w` must not exceed 24.", + "properties": { + "x": { + "description": "Zero-based column of the left edge, 0–23.", + "minimum": 0, + "type": "integer" + }, + "y": { + "description": "Zero-based row of the top edge.", + "minimum": 0, + "type": "integer" + }, + "w": { + "description": "Width in columns, 1–24.", + "maximum": 24, + "minimum": 1, + "type": "integer" + }, + "h": { + "description": "Height in rows, 1–100.", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "x", + "y", + "w", + "h" + ], + "type": "object" + }, + "RumDashboardIDRequest": { + "description": "Request naming one dashboard.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + } + }, + "required": [ + "dashboard_id" + ], + "type": "object" + }, + "RumDashboardLinkMapping": { + "description": "How one variable of the target dashboard is filled when the link is followed.", + "properties": { + "source": { + "description": "Where the value comes from: `variable` (another variable), `row_column` (the clicked row's column), or for bar panels `category`, `series`, `value`.", + "enum": [ + "variable", + "row_column", + "category", + "series", + "value" + ], + "type": "string" + }, + "column": { + "description": "Column of a `row_column` source. At most 1024 characters.", + "maxLength": 1024, + "type": "string" + }, + "name": { + "description": "Variable name of a `variable` source. 1–64 characters starting with a letter or underscore.", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + } + }, + "required": [ + "source" + ], + "type": "object" + }, + "RumDashboardListItem": { + "description": "One row of the dashboard list; the definition is not included.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "title": { + "description": "Dashboard title.", + "type": "string" + }, + "description": { + "description": "Dashboard description.", + "type": "string" + }, + "revision": { + "description": "Current revision number.", + "minimum": 1, + "type": "integer" + }, + "updated_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "updated_at": { + "description": "Last change time as a Unix timestamp in milliseconds.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "title", + "revision", + "updated_by", + "updated_at" + ], + "type": "object" + }, + "RumDashboardListRequest": { + "description": "List request. `p` is 1-based and `limit` defaults to 20, newest first.", + "properties": { + "query": { + "description": "Keyword matched against the dashboard title.", + "type": "string" + }, + "sort": { + "description": "Sort order, at most two unique fields; defaults to `updated_at` descending.", + "items": { + "$ref": "#/components/schemas/RumDashboardListSort" + }, + "maxItems": 2, + "type": "array" + }, + "p": { + "default": 1, + "description": "Page number, 1-based. Defaults to 1.", + "minimum": 1, + "type": "integer" + }, + "limit": { + "default": 20, + "description": "Page size, 1–100. Defaults to 20.", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "type": "object" + }, + "RumDashboardListResponse": { + "description": "One page of dashboards.", + "properties": { + "items": { + "description": "Dashboards on this page.", + "items": { + "$ref": "#/components/schemas/RumDashboardListItem" + }, + "type": "array" + }, + "total": { + "description": "Total number of dashboards matching the query.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "items", + "total" + ], + "type": "object" + }, + "RumDashboardListSort": { + "description": "Sort order of the dashboard list.", + "properties": { + "field": { + "description": "`title` or `updated_at`.", + "enum": [ + "title", + "updated_at" + ], + "type": "string" + }, + "direction": { + "description": "`asc` or `desc`.", + "enum": [ + "asc", + "desc" + ], + "type": "string" + } + }, + "required": [ + "field", + "direction" + ], + "type": "object" + }, + "RumDashboardMutationRequest": { + "description": "Delete or restore request. `expected_revision` must match the current revision.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "expected_revision": { + "description": "Revision the caller last read. Must be at least 1.", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "expected_revision" + ], + "type": "object" + }, + "RumDashboardPanel": { + "description": "One panel of a tab.", + "properties": { + "id": { + "description": "Panel ID, a canonical UUIDv7, unique in the dashboard.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "title": { + "description": "Panel title, 1–189 characters.", + "type": "string" + }, + "description": { + "description": "Panel description, at most 1024 characters.", + "maxLength": 1024, + "type": "string" + }, + "grid": { + "$ref": "#/components/schemas/RumDashboardGridPosition" + }, + "datasource_ref": { + "$ref": "#/components/schemas/RumDashboardDatasourceRef" + }, + "queries": { + "description": "Queries of the panel, at most 26 each with a unique `ref_id`.", + "items": { + "$ref": "#/components/schemas/RumDashboardPanelQuery" + }, + "maxItems": 26, + "type": "array" + }, + "viz_config": { + "$ref": "#/components/schemas/RumDashboardVizConfig" + } + }, + "required": [ + "id", + "title", + "grid", + "queries", + "viz_config" + ], + "type": "object" + }, + "RumDashboardPanelQuery": { + "description": "One query inside a panel, identified by a single-letter reference.", + "properties": { + "ref_id": { + "description": "Query reference, a single uppercase letter `A`–`Z`, unique within the panel.", + "pattern": "^[A-Z]$", + "type": "string" + }, + "query": { + "$ref": "#/components/schemas/RumDashboardQuery" + }, + "legend_alias": { + "description": "Legend label for the query's series. At most 1024 characters.", + "maxLength": 1024, + "type": "string" + } + }, + "required": [ + "ref_id", + "query" + ], + "type": "object" + }, + "RumDashboardQuery": { + "description": "One analytics question of a panel: a DQL filter plus the analytics spec and the application it reads.", + "properties": { + "mode": { + "description": "Query mode. Always `range`.", + "enum": [ + "range" + ], + "type": "string" + }, + "expr": { + "description": "DQL filter over the RUM events of the scope. At most 16 KiB.", + "maxLength": 16384, + "type": "string" + }, + "args": { + "$ref": "#/components/schemas/RumDashboardQueryArgs" + }, + "min_step_seconds": { + "description": "Minimum step of the series in seconds; a duration, not a timestamp.", + "format": "int64", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "mode", + "expr", + "args" + ], + "type": "object" + }, + "RumDashboardQueryArgs": { + "additionalProperties": false, + "description": "The analytics spec of a query: which scope, aggregation, field and grouping it reads. Unknown keys are rejected.", + "properties": { + "scope": { + "description": "RUM explorer scope the query reads. One of `session`, `view`, `resource`, `action`, `error`, `long_task`, `vital`.", + "enum": [ + "session", + "view", + "resource", + "action", + "error", + "long_task", + "vital" + ], + "type": "string" + }, + "agg": { + "description": "Aggregation applied to the scope. One of `count`, `count_distinct`, `avg`, `sum`, `min`, `max`, `p50`, `p75`, `p90`, `p95`, `p99`.", + "enum": [ + "count", + "count_distinct", + "avg", + "sum", + "min", + "max", + "p50", + "p75", + "p90", + "p95", + "p99" + ], + "type": "string" + }, + "field": { + "description": "Field key the aggregation reads. Required unless `agg` is `count`.", + "type": "string" + }, + "group_by": { + "description": "Field key to group by. At most 255 characters.", + "maxLength": 255, + "type": "string" + }, + "limit": { + "description": "Maximum number of series returned. One of `5`, `10`, `20`, `50`.", + "enum": [ + "5", + "10", + "20", + "50" + ], + "type": "string" + }, + "draw_style": { + "description": "How the series is drawn: `line` or `bar`.", + "enum": [ + "line", + "bar" + ], + "type": "string" + }, + "application_id": { + "description": "RUM application the query reads. At most 64 characters.", + "maxLength": 64, + "type": "string" + } + }, + "required": [ + "scope", + "agg" + ], + "type": "object" + }, + "RumDashboardQueryVariable": { + "description": "Variable whose options are the values of a RUM field.", + "properties": { + "kind": { + "description": "Variable kind.", + "enum": [ + "query" + ], + "type": "string" + }, + "name": { + "description": "Variable name, referenced as `${name}` in panel queries. 1–64 characters starting with a letter or underscore.", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + }, + "label": { + "description": "Label shown in the variable bar. Defaults to `name` when empty.", + "type": "string" + }, + "selection": { + "$ref": "#/components/schemas/RumDashboardSelectionConfig" + }, + "default": { + "$ref": "#/components/schemas/RumDashboardSelection" + }, + "datasource_ref": { + "$ref": "#/components/schemas/RumDashboardDatasourceRef" + }, + "variable_query": { + "$ref": "#/components/schemas/RumDashboardVariableQuery" + }, + "refresh": { + "description": "When the candidates are re-read: `on_dashboard_load` or `on_time_range_change`.", + "enum": [ + "on_dashboard_load", + "on_time_range_change" + ], + "type": "string" + } + }, + "required": [ + "kind", + "name", + "selection", + "datasource_ref", + "variable_query", + "refresh" + ], + "type": "object" + }, + "RumDashboardRelativeTimeRange": { + "description": "Time range a dashboard opens with. `from` is a relative offset and `to` is fixed at `now`.", + "properties": { + "from": { + "description": "Relative start of the default time range. One of `now-15m`, `now-30m`, `now-1h`, `now-3h`, `now-6h`, `now-12h`, `now-24h`, `now-7d`.", + "enum": [ + "now-15m", + "now-30m", + "now-1h", + "now-3h", + "now-6h", + "now-12h", + "now-24h", + "now-7d" + ], + "type": "string" + }, + "to": { + "description": "End of the range. Always `now`.", + "enum": [ + "now" + ], + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "RumDashboardResource": { + "description": "A dashboard as stored, including its current definition and revision.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "schema_version": { + "description": "Wire schema of the definition. Always `dashboard.v1`.", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "revision": { + "description": "Revision number, starting at 1 and incremented on every change.", + "minimum": 1, + "type": "integer" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + }, + "created_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "updated_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "created_at": { + "description": "Creation time as a Unix timestamp in milliseconds.", + "format": "int64", + "type": "integer" + }, + "updated_at": { + "description": "Last change time as a Unix timestamp in milliseconds.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "revision", + "definition", + "created_by", + "updated_by", + "created_at", + "updated_at" + ], + "type": "object" + }, + "RumDashboardRevisionGetRequest": { + "description": "Request for one revision of a dashboard.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "revision": { + "description": "Revision number to read. Must be at least 1.", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "revision" + ], + "type": "object" + }, + "RumDashboardRevisionItem": { + "description": "One entry of the revision history; the definition is not included.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "revision": { + "description": "Revision number.", + "minimum": 1, + "type": "integer" + }, + "message": { + "description": "Change message supplied with the update, at most 1024 characters.", + "maxLength": 1024, + "type": "string" + }, + "actor": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "created_at": { + "description": "Creation time of this revision as a Unix timestamp in milliseconds.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "revision", + "actor", + "created_at" + ], + "type": "object" + }, + "RumDashboardRevisionListResponse": { + "description": "Revision history of a dashboard, newest first. Up to 20 revisions are kept.", + "properties": { + "items": { + "description": "Revisions of the dashboard.", + "items": { + "$ref": "#/components/schemas/RumDashboardRevisionItem" + }, + "type": "array" + } + }, + "required": [ + "items" + ], + "type": "object" + }, + "RumDashboardRevisionResource": { + "description": "One revision with its full definition.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "schema_version": { + "description": "Wire schema of the definition. Always `dashboard.v1`.", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "revision": { + "description": "Revision number.", + "minimum": 1, + "type": "integer" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + }, + "message": { + "description": "Change message supplied with the update, at most 1024 characters.", + "maxLength": 1024, + "type": "string" + }, + "actor": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "created_at": { + "description": "Creation time of this revision as a Unix timestamp in milliseconds.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "revision", + "definition", + "actor", + "created_at" + ], + "type": "object" + }, + "RumDashboardSection": { + "description": "Collapsible section inside a tab.", + "properties": { + "id": { + "description": "Section ID, a canonical UUIDv7, unique in the dashboard.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "title": { + "description": "Section title, 1–189 characters.", + "type": "string" + }, + "description": { + "description": "Section description, at most 1024 characters.", + "maxLength": 1024, + "type": "string" + }, + "collapsed": { + "description": "Whether the section starts collapsed.", + "type": "boolean" + }, + "panels": { + "description": "Panels of the section.", + "items": { + "$ref": "#/components/schemas/RumDashboardPanel" + }, + "type": "array" + } + }, + "required": [ + "id", + "title", + "collapsed", + "panels" + ], + "type": "object" + }, + "RumDashboardSelection": { + "description": "A variable's selected value(s).", + "properties": { + "kind": { + "description": "`values` selects the listed values; `all` selects everything and must carry no values.", + "enum": [ + "values", + "all" + ], + "type": "string" + }, + "values": { + "description": "Selected values. Required for kind `values`, forbidden for kind `all`.", + "items": { + "description": "One allowed value.", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "RumDashboardSelectionConfig": { + "description": "How the variable bar lets the viewer pick values.", + "properties": { + "mode": { + "description": "`single` allows one value, `multi` allows several.", + "enum": [ + "single", + "multi" + ], + "type": "string" + }, + "include_all": { + "description": "Whether an `All` entry is offered, which a selection of kind `all` requires.", + "type": "boolean" + } + }, + "required": [ + "mode" + ], + "type": "object" + }, + "RumDashboardStatViz": { + "description": "Single reduced value.", + "properties": { + "kind": { + "description": "Panel kind.", + "enum": [ + "stat" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Stat options passed through to the browser renderer.", + "type": "object" + }, + "unit": { + "description": "Display unit of the panel value. One of `unitless`, `ratio`, `percent`, `milliseconds`, `seconds`, `bytes`, `bits`, `count_per_second`, `bytes_per_second`, `bits_per_second`.", + "enum": [ + "unitless", + "ratio", + "percent", + "milliseconds", + "seconds", + "bytes", + "bits", + "count_per_second", + "bytes_per_second", + "bits_per_second" + ], + "type": "string" + }, + "decimals": { + "description": "Number of decimal places to show.", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "value_fields": { + "description": "Field keys whose values are reduced into the displayed number.", + "items": { + "description": "Field key.", + "type": "string" + }, + "type": "array" + }, + "reducer": { + "description": "How the series are reduced to one value. One of `last_non_null`, `min`, `max`, `mean`, `sum`.", + "enum": [ + "last_non_null", + "min", + "max", + "mean", + "sum" + ], + "type": "string" + } + }, + "required": [ + "kind", + "options", + "value_fields", + "reducer" + ], + "type": "object" + }, + "RumDashboardTab": { + "description": "One tab of the dashboard.", + "properties": { + "id": { + "description": "Tab ID, a canonical UUIDv7, unique in the dashboard.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "title": { + "description": "Tab title, 1–189 characters.", + "type": "string" + }, + "description": { + "description": "Tab description, at most 1024 characters.", + "maxLength": 1024, + "type": "string" + }, + "top_panels": { + "description": "Panels pinned above the sections.", + "items": { + "$ref": "#/components/schemas/RumDashboardPanel" + }, + "type": "array" + }, + "sections": { + "description": "Sections of the tab, at most 10.", + "items": { + "$ref": "#/components/schemas/RumDashboardSection" + }, + "maxItems": 10, + "type": "array" + } + }, + "required": [ + "id", + "title", + "top_panels", + "sections" + ], + "type": "object" + }, + "RumDashboardTableViz": { + "description": "Table of grouped rows.", + "properties": { + "kind": { + "description": "Panel kind.", + "enum": [ + "table" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Table options passed through to the browser renderer.", + "type": "object" + }, + "column_options": { + "additionalProperties": { + "$ref": "#/components/schemas/RumDashboardColumnOption" + }, + "description": "Per-column presentation, keyed by column name. At most 100 columns.", + "type": "object" + }, + "sort": { + "description": "Initial sort order of the table.", + "items": { + "$ref": "#/components/schemas/RumDashboardFieldSort" + }, + "type": "array" + }, + "link_columns": { + "description": "Data links rendered as extra columns. At most 5 per table.", + "items": { + "$ref": "#/components/schemas/RumDashboardDataLink" + }, + "type": "array" + } + }, + "required": [ + "kind", + "options" + ], + "type": "object" + }, + "RumDashboardTextViz": { + "description": "Markdown text block.", + "properties": { + "kind": { + "description": "Panel kind.", + "enum": [ + "text" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Text options passed through to the browser renderer.", + "type": "object" + }, + "markdown": { + "description": "Markdown body, at most 64 KiB. Text panels take no datasource or query.", + "maxLength": 65536, + "type": "string" + } + }, + "required": [ + "kind", + "options", + "markdown" + ], + "type": "object" + }, + "RumDashboardThreshold": { + "description": "Warning/critical thresholds drawn on a numeric panel.", + "properties": { + "mode": { + "description": "Which direction is worse: `higher_is_worse` or `lower_is_worse`.", + "enum": [ + "higher_is_worse", + "lower_is_worse" + ], + "type": "string" + }, + "warning": { + "description": "Warning threshold. Not above `critical` when `mode` is `higher_is_worse`, not below it otherwise.", + "type": "number" + }, + "critical": { + "description": "Critical threshold.", + "type": "number" + } + }, + "required": [ + "mode" + ], + "type": "object" + }, + "RumDashboardTimeSeriesViz": { + "description": "Line or area chart over time.", + "properties": { + "kind": { + "description": "Panel kind.", + "enum": [ + "time_series" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Chart options passed through to the browser renderer.", + "type": "object" + }, + "unit": { + "description": "Display unit of the panel value. One of `unitless`, `ratio`, `percent`, `milliseconds`, `seconds`, `bytes`, `bits`, `count_per_second`, `bytes_per_second`, `bits_per_second`.", + "enum": [ + "unitless", + "ratio", + "percent", + "milliseconds", + "seconds", + "bytes", + "bits", + "count_per_second", + "bytes_per_second", + "bits_per_second" + ], + "type": "string" + }, + "decimals": { + "description": "Number of decimal places to show.", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + } + }, + "required": [ + "kind", + "options" + ], + "type": "object" + }, + "RumDashboardTopListViz": { + "description": "Ranked bar list of reduced series.", + "properties": { + "kind": { + "description": "Panel kind.", + "enum": [ + "top_list" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Top-list options passed through to the browser renderer.", + "type": "object" + }, + "unit": { + "description": "Display unit of the panel value. One of `unitless`, `ratio`, `percent`, `milliseconds`, `seconds`, `bytes`, `bits`, `count_per_second`, `bytes_per_second`, `bits_per_second`.", + "enum": [ + "unitless", + "ratio", + "percent", + "milliseconds", + "seconds", + "bytes", + "bits", + "count_per_second", + "bytes_per_second", + "bits_per_second" + ], + "type": "string" + }, + "decimals": { + "description": "Number of decimal places to show.", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "reducer": { + "description": "How the series are reduced to one value. One of `last_non_null`, `min`, `max`, `mean`, `sum`.", + "enum": [ + "last_non_null", + "min", + "max", + "mean", + "sum" + ], + "type": "string" + }, + "sort": { + "description": "Ranking direction: `asc` or `desc`.", + "enum": [ + "asc", + "desc" + ], + "type": "string" + }, + "limit": { + "description": "Number of entries shown, 1–100. Omit to show all.", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "kind", + "options", + "reducer", + "sort" + ], + "type": "object" + }, + "RumDashboardTrashItem": { + "description": "One row of the trash list.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "title": { + "description": "Dashboard title.", + "type": "string" + }, + "description": { + "description": "Dashboard description.", + "type": "string" + }, + "revision": { + "description": "Revision the dashboard was at when deleted.", + "minimum": 1, + "type": "integer" + }, + "deleted_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "deleted_at": { + "description": "Deletion time as a Unix timestamp in milliseconds.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "title", + "revision", + "deleted_by", + "deleted_at" + ], + "type": "object" + }, + "RumDashboardTrashListRequest": { + "description": "Trash list request. `p` is 1-based and `limit` defaults to 20, newest deletion first.", + "properties": { + "sort": { + "description": "Sort order, at most two unique fields; defaults to `deleted_at` descending.", + "items": { + "$ref": "#/components/schemas/RumDashboardTrashListSort" + }, + "maxItems": 2, + "type": "array" + }, + "p": { + "default": 1, + "description": "Page number, 1-based. Defaults to 1.", + "minimum": 1, + "type": "integer" + }, + "limit": { + "default": 20, + "description": "Page size, 1–100. Defaults to 20.", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "type": "object" + }, + "RumDashboardTrashListResponse": { + "description": "One page of deleted dashboards.", + "properties": { + "items": { + "description": "Deleted dashboards on this page.", + "items": { + "$ref": "#/components/schemas/RumDashboardTrashItem" + }, + "type": "array" + }, + "total": { + "description": "Total number of dashboards in the trash.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "items", + "total" + ], + "type": "object" + }, + "RumDashboardTrashListSort": { + "description": "Sort order of the trash list.", + "properties": { + "field": { + "description": "`title` or `deleted_at`.", + "enum": [ + "title", + "deleted_at" + ], + "type": "string" + }, + "direction": { + "description": "`asc` or `desc`.", + "enum": [ + "asc", + "desc" + ], + "type": "string" + } + }, + "required": [ + "field", + "direction" + ], + "type": "object" + }, + "RumDashboardUnitFields": { + "description": "Numeric presentation shared by the value-bearing panel kinds.", + "properties": { + "unit": { + "description": "Display unit of the panel value. One of `unitless`, `ratio`, `percent`, `milliseconds`, `seconds`, `bytes`, `bits`, `count_per_second`, `bytes_per_second`, `bits_per_second`.", + "enum": [ + "unitless", + "ratio", + "percent", + "milliseconds", + "seconds", + "bytes", + "bits", + "count_per_second", + "bytes_per_second", + "bits_per_second" + ], + "type": "string" + }, + "decimals": { + "description": "Number of decimal places to show.", + "maximum": 10, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + } + }, + "type": "object" + }, + "RumDashboardUpdateRequest": { + "description": "Update request. `expected_revision` makes the write conditional: the update fails with `DashboardRevisionConflict` when the dashboard has moved on.", + "properties": { + "dashboard_id": { + "description": "Dashboard ID, a canonical UUIDv7.", + "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", + "type": "string" + }, + "schema_version": { + "description": "Wire schema of the definition. Must be `dashboard.v1`.", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "expected_revision": { + "description": "Revision the caller last read. Must be at least 1.", + "minimum": 1, + "type": "integer" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + }, + "message": { + "description": "Optional change message stored with the revision, at most 1024 characters.", + "maxLength": 1024, + "type": "string" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "expected_revision", + "definition" + ], + "type": "object" + }, + "RumDashboardUpdateResponse": { + "description": "Result of an update. `changed` is `false` when the submitted definition matched the stored one, in which case `resource` is still returned.", + "properties": { + "changed": { + "description": "Whether the stored definition actually changed.", + "type": "boolean" + }, + "resource": { + "$ref": "#/components/schemas/RumDashboardResource" + } + }, + "required": [ + "changed", + "resource" + ], + "type": "object" + }, + "RumDashboardVariable": { + "description": "One entry of the variable bar. The `kind` field selects the shape: `custom` carries a fixed option list, `query` reads the values of a RUM field.", + "discriminator": { + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/RumDashboardCustomVariable" + }, + { + "$ref": "#/components/schemas/RumDashboardQueryVariable" + } + ] + }, + "RumDashboardVariableQuery": { + "description": "Where a query variable takes its candidates from. RUM lists the values of one RUM field.", + "properties": { + "kind": { + "description": "Query kind. Always `rum_field`.", + "enum": [ + "rum_field" + ], + "type": "string" + }, + "field": { + "description": "RUM field key whose values become the candidates.", + "type": "string" + } + }, + "required": [ + "kind", + "field" + ], + "type": "object" + }, + "RumDashboardVizConfig": { + "description": "How a panel renders its queries. The `kind` field selects one of six shapes: `time_series`, `table`, `stat`, `bar`, `top_list`, `text`.", + "discriminator": { + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/RumDashboardTimeSeriesViz" + }, + { + "$ref": "#/components/schemas/RumDashboardTableViz" + }, + { + "$ref": "#/components/schemas/RumDashboardStatViz" + }, + { + "$ref": "#/components/schemas/RumDashboardBarViz" + }, + { + "$ref": "#/components/schemas/RumDashboardTopListViz" + }, + { + "$ref": "#/components/schemas/RumDashboardTextViz" + } + ] + } + }, + "securitySchemes": { + "AppKeyAuth": { + "type": "apiKey", + "in": "query", + "name": "app_key", + "description": "APP Key created in the Flashduty console under My → APP Key. Send it as the `app_key` query parameter or in the `Fd-App-Key` request header. Its effective access is the intersection of the key's permission scope and the creator's current role permissions. Keep it secret." + } + } + }, + "info": { + "description": "Public HTTP API for the Flashduty incident management platform — incidents, notification templates, channels, schedules, monitors, RUM, and platform administration. Every operation is authenticated with an `app_key` query parameter issued from the Flashduty console under Account → APP Keys. Responses follow a uniform envelope: `{ request_id, data }` on success, `{ request_id, error }` on failure.", + "title": "Flashduty Open API", + "version": "1.0.0" + }, + "openapi": "3.1.0", + "paths": { + "/account/info": { + "post": { + "summary": "Get account detail", + "description": "Return the current account's profile and settings.", + "operationId": "account-read-info", + "tags": [ + "Platform/Account" + ], + "security": [ + { + "AppKeyAuth": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object" + }, + "example": {} + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AccountInfo" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "account_id": 1001, + "account_name": "acme", + "domain": "acme", + "extra_domains": [ + "acme-corp" + ], + "phone": "138****8000", + "country_code": "CN", + "email": "ops@acme.example", + "avatar": "https://example.com/avatar/acme.png", + "locale": "zh-CN", + "time_zone": "Asia/Shanghai", + "created_at": 1716960000, + "restrictions": { + "ips": [ + "203.0.113.0/24" + ], + "email_domains": [ + "acme.example" + ], + "allow_subdomain": true + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "x-mint": { + "metadata": { + "sidebarTitle": "Get account detail" + }, + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — but see the credential requirement under Usage |\n\n## Usage\n\n- Requires the account owner's credentials (for example an app key created by the account owner); member credentials return `401 Unauthorized`. Members can use `POST /member/info` instead.\n- `restrictions` is present only when join or access restrictions have been configured; `mp_plat` and `mp_account_id` only for accounts provisioned through a cloud marketplace.", + "href": "/en/api-reference/platform/account/account-read-info" + } + } + }, + "/alert-event/list": { + "post": { + "operationId": "alert-event-read-list", + "summary": "List raw alert events", + "description": "Return a cursor-paginated list of raw alert events across all alerts, with filtering by integration, channel, time range, and severity.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Both `start_time` and `end_time` are required Unix epoch seconds. `start_time` must be less than `end_time`; the span must not exceed 31 days.\n- Results are filtered by the caller's channel data-access permissions. When `channel_ids` is sent and none of the listed channels is accessible to the caller, the result is empty.\n- `severities` is a comma-separated list matched against `event_severity`, e.g. `\"Critical,Warning\"`. Values are not validated, so an unknown value (or `Ok`) matches nothing.\n- Pass `search_after_ctx` from the previous response for the next page; without it, `p`/`limit` page numbers apply and `p * limit` must stay within 10,000.", + "href": "/en/api-reference/on-call/alerts/alert-event-read-list", + "metadata": { + "sidebarTitle": "List raw alert events" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertEventGlobalListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 1, + "has_next_page": false, + "items": [ + { + "event_id": "663a1b2c3d4e5f6789abc001", + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%", + "event_severity": "Critical", + "event_time": 1712650000 + } + ], + "search_after_ctx": "663a1b2c3d4e5f6789abc001" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertEventGlobalListRequest" + }, + "example": { + "start_time": 1712620800, + "end_time": 1712707200, + "limit": 20, + "severities": "Critical" + } + } + } + } + } + }, + "/alert/event/list": { + "post": { + "operationId": "alert-read-event-list", + "summary": "List events for an alert", + "description": "Return raw events for an alert with cursor or page-number pagination.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- Results are newest-first by default. Set `asc=true` to read events oldest-first.\n- Use `limit` with `search_after_ctx` from the previous response to fetch the next page.\n- Classic page-number pagination is also supported with `p`, but `p * limit` must stay within 10,000 records.\n- An `alert_id` not found in the account returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-event-list", + "metadata": { + "sidebarTitle": "List events for an alert" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertEventListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 57, + "has_next_page": true, + "search_after_ctx": "663a1b2c3d4e5f6789abc001", + "items": [ + { + "event_id": "663a1b2c3d4e5f6789abc001", + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%", + "event_severity": "Critical", + "event_status": "Critical", + "event_time": 1712650000, + "labels": { + "host": "web-01" + } + } + ] + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertEventListRequest" + }, + "example": { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "limit": 20 + } + } + } + } + } + }, + "/alert/feed": { + "post": { + "operationId": "alert-read-feed", + "summary": "List alert activity feed", + "description": "Return the activity feed (comments, state changes, merges, silence events) for a single alert, with page-based pagination.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Use `p` (page number, starting at 1) and `limit` (max 100, default 20) for pagination.\n- Set `asc` to `true` for chronological order.\n- Use `types` to filter by specific feed types (e.g. `a_comm`, `a_merge`).\n- An `alert_id` not found in the account returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-feed", + "metadata": { + "sidebarTitle": "List alert activity feed" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertFeedResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "has_next_page": false, + "items": [ + { + "ref_id": "663a1b2c3d4e5f6789abcdef", + "type": "a_comm", + "detail": { + "comment": "Investigating now." + }, + "account_id": 10023, + "creator_id": 80011, + "created_at": 1712651000000, + "updated_at": 1712651000000 + } + ] + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertFeedRequest" + }, + "example": { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "limit": 20, + "asc": false + } + } + } + } + } + }, + "/alert/info": { + "post": { + "operationId": "alert-read-info", + "summary": "Get alert detail", + "description": "Return the full details of a single alert by its ID, including its associated incident and event count.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- `alert_id` is an ObjectID hex string returned by `POST /alert/list` or `POST /alert-event/list`.\n- An `alert_id` not found in the account returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-info", + "metadata": { + "sidebarTitle": "Get alert detail" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertItem" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%", + "alert_severity": "Critical", + "alert_status": "Critical", + "start_time": 1712650000, + "event_cnt": 3 + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertInfoRequest" + }, + "example": { + "alert_id": "663a1b2c3d4e5f6789abcdef" + } + } + } + } + } + }, + "/alert/list": { + "post": { + "operationId": "alert-read-list", + "summary": "List alerts", + "description": "Return a cursor-paginated list of alerts matching the given filters.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- `start_time` and `end_time` are required Unix seconds and filter on the alert's `start_time`; the span must not exceed 31 days.\n- With `by_updated_at: true`, an `updated_at` window with the same bounds is added on top of the `start_time` filter, and the span must not exceed 7 days.\n- A `start_time` earlier than the account's data retention period is moved up to the retention start; an `end_time` before that start returns `InvalidParameter`.\n- Pass `search_after_ctx` from the previous response for the next page; without it, `p`/`limit` page numbers apply and `p * limit` must stay within 10,000.\n- `total` is capped at 1,000. `has_next_page` does not depend on `total`: it is exact in both page-number and cursor mode, also past 1,000 alerts. Every non-empty page returns `search_after_ctx` for its last alert; pass it back to read past the 10,000-row page-number limit.\n- Results are filtered by the caller's channel data-access permissions.\n- Set `is_active` to `true` to retrieve only active (firing) alerts; `false` to retrieve resolved alerts.", + "href": "/en/api-reference/on-call/alerts/alert-read-list", + "metadata": { + "sidebarTitle": "List alerts" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 1, + "has_next_page": false, + "items": [ + { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "integration_id": 10001, + "channel_id": 20001, + "account_id": 10023, + "title": "CPU usage > 90%", + "alert_severity": "Critical", + "alert_status": "Critical", + "start_time": 1712650000, + "last_time": 1712655000, + "end_time": 0, + "labels": { + "host": "web-01" + }, + "ever_muted": false, + "created_at": 1712650000, + "updated_at": 1712655000, + "integration_name": "Prometheus", + "integration_type": "prometheus", + "channel_name": "Production", + "event_cnt": 3 + } + ], + "search_after_ctx": "663a1b2c3d4e5f6789abcdef" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertListRequest" + }, + "example": { + "start_time": 1712620800, + "end_time": 1712707200, + "limit": 20, + "is_active": true + } + } + } + } } }, - "securitySchemes": { - "AppKeyAuth": { - "type": "apiKey", - "in": "query", - "name": "app_key", - "description": "APP Key created in the Flashduty console under My → APP Key. Send it as the `app_key` query parameter or in the `Fd-App-Key` request header. Its effective access is the intersection of the key's permission scope and the creator's current role permissions. Keep it secret." + "/alert/list-by-ids": { + "post": { + "operationId": "alert-read-list-by-ids", + "summary": "List alerts by IDs", + "description": "Return the details of several alerts by ID in one request, without pagination.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- A malformed ID fails the request with `InvalidParameter`; well-formed IDs not found in the account are left out of `items`.\n- The response is not paginated: `total` is always `0`, `has_next_page` is always `false`, and `search_after_ctx` is omitted.", + "href": "/en/api-reference/on-call/alerts/alert-read-list-by-ids", + "metadata": { + "sidebarTitle": "List alerts by IDs" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 0, + "has_next_page": false, + "items": [ + { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%" + } + ] + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertListByIDsRequest" + }, + "example": { + "alert_ids": [ + "663a1b2c3d4e5f6789abcdef" + ] + } + } + } + } } - } - }, - "info": { - "description": "Public HTTP API for the Flashduty incident management platform — incidents, notification templates, channels, schedules, monitors, RUM, and platform administration. Every operation is authenticated with an `app_key` query parameter issued from the Flashduty console under Account → APP Keys. Responses follow a uniform envelope: `{ request_id, data }` on success, `{ request_id, error }` on failure.", - "title": "Flashduty Open API", - "version": "1.0.0" - }, - "openapi": "3.1.0", - "paths": { - "/account/info": { + }, + "/alert/merge": { "post": { - "summary": "Get account detail", - "description": "Return the current account's profile and settings.", - "operationId": "account-read-info", + "operationId": "alert-write-merge", + "summary": "Merge alerts into an incident", + "description": "Move one or more alerts into an existing incident and close source incidents left empty.", "tags": [ - "Platform/Account" + "On-call/Alerts" ], - "security": [ - { - "AppKeyAuth": [] + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Every `alert_ids` entry and the `incident_id` must belong to the account; an unknown ID returns `InvalidParameter`.\n- Alerts already in the target incident are skipped. A source incident left with no alerts is closed.\n- `title` and `owner_id` update the target incident only when they differ from its current values.\n- Only one incident change runs per account at a time; a concurrent call returns `RequestTooFrequently`.", + "href": "/en/api-reference/on-call/alerts/alert-write-merge", + "metadata": { + "sidebarTitle": "Merge alerts into an incident" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EmptyObject" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertMergeRequest" + }, + "example": { + "alert_ids": [ + "663a1b2c3d4e5f6789abcdef" + ], + "incident_id": "663a000000000000deadbeef" + } + } + } + } + } + }, + "/alert/pipeline/info": { + "post": { + "operationId": "alert-read-pipeline-info", + "summary": "Get alert pipeline", + "description": "Return the alert processing pipeline configured for a specific integration.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- When the integration has no pipeline, the response carries only `request_id` and the `data` field is omitted.\n- `integration_id` may be any account-level or channel-owned integration of the account; an unknown ID returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-info", + "metadata": { + "sidebarTitle": "Get alert pipeline" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelineItem" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "integration_id": 10001, + "rules": [ + { + "kind": "title_reset", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "prod" + ] + } + ], + "settings": { + "title": "[TPL]{{.Labels.service}} / {{.Labels.check}}" + } + }, + { + "kind": "severity_reset", + "if": null, + "settings": { + "severity": "Warning" + } + } + ], + "status": "enabled", + "creator_id": 80011, + "updated_by": 80011, + "created_at": 1710000000, + "updated_at": 1712000000 + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertPipelineInfoRequest" + }, + "example": { + "integration_id": 10001 + } + } + } + } + } + }, + "/alert/pipeline/list": { + "post": { + "operationId": "alert-read-pipeline-list", + "summary": "List alert pipelines", + "description": "Return the alert processing pipelines configured for multiple integrations.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Every `integration_ids` entry must be an integration of the account; one unknown ID fails the whole request with `InvalidParameter`.\n- `items` holds one entry per integration that has a pipeline; integrations without one are absent.", + "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-list", + "metadata": { + "sidebarTitle": "List alert pipelines" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelineListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "integration_id": 10001, + "rules": [ + { + "kind": "alert_inhibit", + "if": [ + { + "key": "labels.cluster", + "oper": "IN", + "vals": [ + "prod-cn" + ] + } + ], + "settings": { + "equals": [ + "labels.service" + ], + "source_filters": [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Critical" + ] + } + ] + } + } + ], + "status": "enabled", + "creator_id": 80011, + "updated_by": 80011, + "created_at": 1710000000, + "updated_at": 1712000000 + } + ] + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertPipelineListRequest" + }, + "example": { + "integration_ids": [ + 10001, + 10002 + ] + } + } + } + } + } + }, + "/alert/pipeline/upsert": { + "post": { + "operationId": "alert-write-pipeline-upsert", + "summary": "Create or update alert pipeline", + "description": "Set the alert processing pipeline for an integration. Replaces the existing configuration entirely.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Replaces the integration's whole rule list with `rules`; an empty array removes every rule. At most 50 rules.\n- Rules run in array order on each incoming event of the integration before it becomes an alert; `alert_drop`, or an `alert_inhibit` that matches, discards the event and stops processing.\n- `integration_id` may be an account-level or a channel-owned integration; an ID not in the account returns `InvalidParameter`.\n- Write access also requires object permission: the account owner, an administrator, the integration creator, or a member of its team (for a channel-owned integration, a member of the channel's team); with no team, any caller with the API permission may write.\n- An `alert_inhibit` rule requires the Standard plan or higher; otherwise the call returns `NoLicense`.\n- On success the response carries only `request_id`; the `data` field is omitted.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/alerts/alert-write-pipeline-upsert", + "metadata": { + "sidebarTitle": "Create or update alert pipeline" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" } - ], + }, "requestBody": { + "required": true, "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/AlertPipelineUpsertRequest" }, - "example": {} + "example": { + "integration_id": 10001, + "rules": [ + { + "kind": "title_reset", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "prod" + ] + } + ], + "settings": { + "title": "[TPL]{{.Labels.service}} / {{.Labels.check}}" + } + }, + { + "kind": "severity_reset", + "if": null, + "settings": { + "severity": "Warning" + } + } + ] + } } } + } + } + }, + "/audit/operation/list": { + "post": { + "operationId": "audit-read-operation-list", + "summary": "List auditable operation types", + "description": "Return all operation names that are recorded in the audit log, for use as `operations` filter values.", + "tags": [ + "Platform/Audit logs" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Use the `name` values from this response as `operations` filter values in `POST /audit/search`.\n- `name_cn` is the Chinese label shown in the console, returned in Chinese regardless of the request language; `name` is the stable value to filter on.", + "href": "/en/api-reference/platform/audit-logs/audit-read-operation-list", + "metadata": { + "sidebarTitle": "List auditable operation types" + } }, "responses": { "200": { @@ -34590,7 +37295,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AccountInfo" + "$ref": "#/components/schemas/AuditOperationListResponse" } } } @@ -34599,28 +37304,20 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "account_id": 1001, - "account_name": "acme", - "domain": "acme", - "extra_domains": [ - "acme-corp" - ], - "phone": "138****8000", - "country_code": "CN", - "email": "ops@acme.example", - "avatar": "https://example.com/avatar/acme.png", - "locale": "zh-CN", - "time_zone": "Asia/Shanghai", - "created_at": 1716960000, - "restrictions": { - "ips": [ - "203.0.113.0/24" - ], - "email_domains": [ - "acme.example" - ], - "allow_subdomain": true - } + "items": [ + { + "name": "template:write:create", + "name_cn": "创建模板" + }, + { + "name": "template:write:delete", + "name_cn": "删除模板" + }, + { + "name": "incident:write:acknowledge", + "name_cn": "认领故障" + } + ] } } } @@ -34642,28 +37339,32 @@ "$ref": "#/components/responses/ServerError" } }, - "x-mint": { - "metadata": { - "sidebarTitle": "Get account detail" - }, - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — but see the credential requirement under Usage |\n\n## Usage\n\n- Requires the account owner's credentials (for example an app key created by the account owner); member credentials return `401 Unauthorized`. Members can use `POST /member/info` instead.\n- `restrictions` is present only when join or access restrictions have been configured; `mp_plat` and `mp_account_id` only for accounts provisioned through a cloud marketplace.", - "href": "/en/api-reference/platform/account/account-read-info" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditOperationListRequest" + }, + "example": {} + } + } } } }, - "/alert-event/list": { + "/audit/search": { "post": { - "operationId": "alert-event-read-list", - "summary": "List raw alert events", - "description": "Return a cursor-paginated list of raw alert events across all alerts, with filtering by integration, channel, time range, and severity.", + "operationId": "audit-read-search", + "summary": "Search audit logs", + "description": "Return a cursor-paginated list of audit log entries within a time range.", "tags": [ - "On-call/Alerts" + "Platform/Audit logs" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Both `start_time` and `end_time` are required Unix epoch seconds. `start_time` must be less than `end_time`; the span must not exceed 31 days.\n- Results are filtered by the caller's channel data-access permissions. When `channel_ids` is sent and none of the listed channels is accessible to the caller, the result is empty.\n- `severities` is a comma-separated list matched against `event_severity`, e.g. `\"Critical,Warning\"`. Values are not validated, so an unknown value (or `Ok`) matches nothing.\n- Pass `search_after_ctx` from the previous response for the next page; without it, `p`/`limit` page numbers apply and `p * limit` must stay within 10,000.", - "href": "/en/api-reference/on-call/alerts/alert-event-read-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Time range is required. Maximum span is 90 days. Both `start_time` and `end_time` are Unix epoch **seconds**.\n- Use `search_after_ctx` from the previous response to fetch the next page. The token is opaque — do not construct it manually.\n- The retention window depends on the account's license. Queries beyond the retention boundary silently return an empty result rather than an error.\n- Pass an explicit `limit` (1–99) for predictable paging; when it is omitted or 0 the server chooses the page size, which may be the whole result set. Entries are returned newest first.", + "href": "/en/api-reference/platform/audit-logs/audit-read-search", "metadata": { - "sidebarTitle": "List raw alert events" + "sidebarTitle": "Search audit logs" } }, "responses": { @@ -34680,7 +37381,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertEventGlobalListResponse" + "$ref": "#/components/schemas/AuditSearchResponse" } } } @@ -34689,18 +37390,27 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 1, - "has_next_page": false, - "items": [ + "total": 2, + "search_after_ctx": "", + "docs": [ { - "event_id": "663a1b2c3d4e5f6789abc001", - "alert_id": "663a1b2c3d4e5f6789abcdef", - "title": "CPU usage > 90%", - "event_severity": "Critical", - "event_time": 1712650000 + "created_at": 1712700123456, + "account_id": 10023, + "member_id": 80011, + "member_name": "Alice", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "ip": "203.0.113.42", + "operation": "template:write:create", + "operation_name": "创建模板", + "body": "{\"template_name\":\"Prod default\"}", + "params": [], + "is_dangerous": false, + "is_write": true, + "principal_kind": "member", + "credential_type": "", + "credential_id": 0 } - ], - "search_after_ctx": "663a1b2c3d4e5f6789abc001" + ] } } } @@ -34727,32 +37437,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertEventGlobalListRequest" + "$ref": "#/components/schemas/AuditSearchRequest" }, "example": { "start_time": 1712620800, "end_time": 1712707200, "limit": 20, - "severities": "Critical" + "operations": [ + "template:write:create", + "template:write:delete" + ] } } } } } }, - "/alert/event/list": { + "/calendar/create": { "post": { - "operationId": "alert-read-event-list", - "summary": "List events for an alert", - "description": "Return raw events for an alert with cursor or page-number pagination.", + "operationId": "calendarCreate", + "summary": "Create calendar", + "description": "Create a personal service calendar with its weekly workdays and linked holiday calendars.", "tags": [ - "On-call/Alerts" + "On-call/Calendars" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- Results are newest-first by default. Set `asc=true` to read events oldest-first.\n- Use `limit` with `search_after_ctx` from the previous response to fetch the next page.\n- Classic page-number pagination is also supported with `p`, but `p * limit` must stay within 10,000 records.\n- An `alert_id` not found in the account returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/alerts/alert-read-event-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- An account can hold at most 5 calendars: once it has 5, a create call by any member returns `InvalidParameter`.\n- `cal_name` must be unique within the account, `timezone` must be a valid IANA name, and a nonzero `team_id` must be a team of the account; otherwise the call returns `InvalidParameter`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/calendar-create", "metadata": { - "sidebarTitle": "List events for an alert" + "sidebarTitle": "Create calendar" } }, "responses": { @@ -34769,7 +37482,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertEventListResponse" + "$ref": "#/components/schemas/CalendarCreateResponse" } } } @@ -34778,22 +37491,8 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 57, - "has_next_page": true, - "search_after_ctx": "663a1b2c3d4e5f6789abc001", - "items": [ - { - "event_id": "663a1b2c3d4e5f6789abc001", - "alert_id": "663a1b2c3d4e5f6789abcdef", - "title": "CPU usage > 90%", - "event_severity": "Critical", - "event_status": "Critical", - "event_time": 1712650000, - "labels": { - "host": "web-01" - } - } - ] + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "cal_name": "API Test Calendar" } } } @@ -34820,30 +37519,38 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertEventListRequest" + "$ref": "#/components/schemas/CalendarCreateRequest" }, "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "limit": 20 + "cal_name": "Production On-Call Calendar", + "description": "Calendar for production on-call team", + "timezone": "Asia/Shanghai", + "workdays": [ + 1, + 2, + 3, + 4, + 5 + ] } } } } } }, - "/alert/feed": { + "/calendar/delete": { "post": { - "operationId": "alert-read-feed", - "summary": "List alert activity feed", - "description": "Return the activity feed (comments, state changes, merges, silence events) for a single alert, with page-based pagination.", + "operationId": "calendarDelete", + "summary": "Delete calendar", + "description": "Delete a personal service calendar and its events when no rule references it.", "tags": [ - "On-call/Alerts" + "On-call/Calendars" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Use `p` (page number, starting at 1) and `limit` (max 100, default 20) for pagination.\n- Set `asc` to `true` for chronological order.\n- Use `types` to filter by specific feed types (e.g. `a_comm`, `a_merge`).\n- An `alert_id` not found in the account returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/alerts/alert-read-feed", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- If escalation rules or silence rules still use the calendar, the call returns HTTP 400 with `error.code` = `ReferenceExist` and `data.refs` listing them.\n- The calendar's own events are deleted together with it.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/calendar-delete", "metadata": { - "sidebarTitle": "List alert activity feed" + "sidebarTitle": "Delete calendar" } }, "responses": { @@ -34860,7 +37567,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertFeedResponse" + "$ref": "#/components/schemas/CalendarEmptyObject" } } } @@ -34868,22 +37575,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "has_next_page": false, - "items": [ - { - "ref_id": "663a1b2c3d4e5f6789abcdef", - "type": "a_comm", - "detail": { - "comment": "Investigating now." - }, - "account_id": 10023, - "creator_id": 80011, - "created_at": 1712651000000, - "updated_at": 1712651000000 - } - ] - } + "data": {} } } } @@ -34909,31 +37601,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertFeedRequest" + "$ref": "#/components/schemas/CalendarIDRequest" }, "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "limit": 20, - "asc": false + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM" } } } } } }, - "/alert/info": { + "/calendar/event/delete": { "post": { - "operationId": "alert-read-info", - "summary": "Get alert detail", - "description": "Return the full details of a single alert by its ID, including its associated incident and event count.", + "operationId": "calEventDelete", + "summary": "Delete calendar event", + "description": "Delete one personal-calendar event by ID, or clear the calendar's own events from a date range.", "tags": [ - "On-call/Alerts" + "On-call/Calendars" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- `alert_id` is an ObjectID hex string returned by `POST /alert/list` or `POST /alert-event/list`.\n- An `alert_id` not found in the account returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/alerts/alert-read-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- Pass either `event_id`, or both `start_at` and `end_at` (dates in `YYYY-MM-DD`, covering [`start_at`, `end_at`)); any other combination returns `InvalidParameter`.\n- Cleared days fall back to the linked holiday calendars and the weekly workdays.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/cal-event-delete", "metadata": { - "sidebarTitle": "Get alert detail" + "sidebarTitle": "Delete calendar event" } }, "responses": { @@ -34950,7 +37640,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertItem" + "$ref": "#/components/schemas/CalendarEmptyObject" } } } @@ -34958,14 +37648,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "title": "CPU usage > 90%", - "alert_severity": "Critical", - "alert_status": "Critical", - "start_time": 1712650000, - "event_cnt": 3 - } + "data": {} } } } @@ -34991,29 +37674,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertInfoRequest" + "$ref": "#/components/schemas/CalEventIDRequest" }, "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef" + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4" } } } } } }, - "/alert/list": { + "/calendar/event/list": { "post": { - "operationId": "alert-read-list", - "summary": "List alerts", - "description": "Return a cursor-paginated list of alerts matching the given filters.", + "operationId": "calEventList", + "summary": "List calendar events", + "description": "Return a personal calendar's events for a year, month or day, plus the resolved state of each day.", "tags": [ - "On-call/Alerts" + "On-call/Calendars" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- `start_time` and `end_time` are required Unix seconds and filter on the alert's `start_time`; the span must not exceed 31 days.\n- With `by_updated_at: true`, an `updated_at` window with the same bounds is added on top of the `start_time` filter, and the span must not exceed 7 days.\n- A `start_time` earlier than the account's data retention period is moved up to the retention start; an `end_time` before that start returns `InvalidParameter`.\n- Pass `search_after_ctx` from the previous response for the next page; without it, `p`/`limit` page numbers apply and `p * limit` must stay within 10,000.\n- `total` is capped at 1,000. `has_next_page` does not depend on `total`: it is exact in both page-number and cursor mode, also past 1,000 alerts. Every non-empty page returns `search_after_ctx` for its last alert; pass it back to read past the 10,000-row page-number limit.\n- Results are filtered by the caller's channel data-access permissions.\n- Set `is_active` to `true` to retrieve only active (firing) alerts; `false` to retrieve resolved alerts.", - "href": "/en/api-reference/on-call/alerts/alert-read-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- `year` defaults to the current year; without `month` the whole year is returned, and `day` requires `month`.\n- `items` merges the calendar's own events (`cale.*` IDs), one generated `non_work.YYYYMMDD` entry per non-working weekday when `workdays` is set, and the events of the linked holiday calendars; `total` counts all of them.\n- `days` gives the resolved state of every day in the scope.\n- Only personal calendars (`cal_id` starting with `cal.`) are supported; other IDs return `InvalidParameter`.", + "href": "/en/api-reference/on-call/calendars/cal-event-list", "metadata": { - "sidebarTitle": "List alerts" + "sidebarTitle": "List calendar events" } }, "responses": { @@ -35030,7 +37714,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertListResponse" + "$ref": "#/components/schemas/CalEventListResponse" } } } @@ -35039,33 +37723,55 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 1, - "has_next_page": false, "items": [ { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "integration_id": 10001, - "channel_id": 20001, - "account_id": 10023, - "title": "CPU usage > 90%", - "alert_severity": "Critical", - "alert_status": "Critical", - "start_time": 1712650000, - "last_time": 1712655000, - "end_time": 0, - "labels": { - "host": "web-01" - }, - "ever_muted": false, - "created_at": 1712650000, - "updated_at": 1712655000, - "integration_name": "Prometheus", - "integration_type": "prometheus", - "channel_name": "Production", - "event_cnt": 3 + "account_id": 2451002751131, + "creator_id": 2476444212131, + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", + "summary": "Test Holiday", + "description": "A test holiday event", + "start_at": "2026-05-01", + "end_at": "2026-05-02", + "is_off": true, + "created_at": 1775972034, + "updated_at": 1775972034 + }, + { + "account_id": 2451002751131, + "creator_id": 2451002751131, + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "non_work.20260502", + "summary": "non-working day (Saturday)", + "description": "", + "start_at": "2026-05-02", + "end_at": "2026-05-03", + "is_off": true, + "created_at": 0, + "updated_at": 0 } ], - "search_after_ctx": "663a1b2c3d4e5f6789abcdef" + "total": 11, + "days": { + "2026-05-01": { + "is_off": true, + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", + "layer": "custom" + }, + "2026-05-02": { + "is_off": true, + "event_id": "non_work.20260502", + "layer": "weekly" + }, + "2026-05-09": { + "is_off": false, + "event_id": "zh-cn.china.official.c234057c-fd90-380e-889c-3e3254dd5b01", + "layer": "holiday" + }, + "2026-05-11": { + "is_off": false + } + } } } } @@ -35092,32 +37798,113 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertListRequest" + "$ref": "#/components/schemas/CalEventListRequest" }, "example": { - "start_time": 1712620800, - "end_time": 1712707200, - "limit": 20, - "is_active": true + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "year": 2024, + "month": 5 } } } } } }, - "/alert/list-by-ids": { + "/calendar/event/upsert": { "post": { - "operationId": "alert-read-list-by-ids", - "summary": "List alerts by IDs", - "description": "Return the details of several alerts by ID in one request, without pagination.", + "operationId": "calEventUpsert", + "summary": "Upsert calendar event", + "description": "Create or update one of a personal calendar's own events: a day off or a working-day override.", "tags": [ - "On-call/Alerts" + "On-call/Calendars" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- A malformed ID fails the request with `InvalidParameter`; well-formed IDs not found in the account are left out of `items`.\n- The response is not paginated: `total` is always `0`, `has_next_page` is always `false`, and `search_after_ctx` is omitted.", - "href": "/en/api-reference/on-call/alerts/alert-read-list-by-ids", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- The event covers the days [`start_at`, `end_at`), dates in `YYYY-MM-DD`; `end_at` must be later than `start_at`.\n- Omit `event_id` to create an event; a given `event_id` must be an existing event of this calendar.\n- The write clears the calendar's other own events off the same days: an event fully inside the range is deleted, one partly inside is shortened, and one spanning the range is split in two, so the latest write decides those days.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/cal-event-upsert", + "metadata": { + "sidebarTitle": "Upsert calendar event" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/CalEventUpsertResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", + "summary": "Test Holiday" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CalEventUpsertRequest" + }, + "example": { + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "summary": "Labour Day", + "start_at": "2024-05-01", + "end_at": "2024-05-06", + "is_off": true, + "description": "International Workers Day holiday" + } + } + } + } + } + }, + "/calendar/info": { + "post": { + "operationId": "calendarInfo", + "summary": "Get calendar info", + "description": "Return the details of one service calendar of the account by its ID.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- An unknown `cal_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/calendars/calendar-info", "metadata": { - "sidebarTitle": "List alerts by IDs" + "sidebarTitle": "Get calendar info" } }, "responses": { @@ -35134,7 +37921,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertListResponse" + "$ref": "#/components/schemas/CalendarItem" } } } @@ -35143,14 +37930,27 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 0, - "has_next_page": false, - "items": [ - { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "title": "CPU usage > 90%" - } - ] + "account_id": 2451002751131, + "team_id": 2477033058131, + "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg", + "cal_name": "Stock Exchange Calendar", + "description": "A stock market trading calendar example", + "timezone": "Asia/Shanghai", + "kind": "personal", + "workdays": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "created_at": 1702455630, + "updated_at": 1775529526, + "creator_id": 2476444212131, + "updated_by": 3790925372131, + "status": "enabled" } } } @@ -35177,31 +37977,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertListByIDsRequest" + "$ref": "#/components/schemas/CalendarIDRequest" }, "example": { - "alert_ids": [ - "663a1b2c3d4e5f6789abcdef" - ] + "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg" } } } } } }, - "/alert/merge": { + "/calendar/list": { "post": { - "operationId": "alert-write-merge", - "summary": "Merge alerts into an incident", - "description": "Move one or more alerts into an existing incident and close source incidents left empty.", + "operationId": "calendarList", + "summary": "List calendars", + "description": "Return the list of service calendars visible to the current account.", "tags": [ - "On-call/Alerts" + "On-call/Calendars" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Every `alert_ids` entry and the `incident_id` must belong to the account; an unknown ID returns `InvalidParameter`.\n- Alerts already in the target incident are skipped. A source incident left with no alerts is closed.\n- `title` and `owner_id` update the target incident only when they differ from its current values.\n- Only one incident change runs per account at a time; a concurrent call returns `RequestTooFrequently`.", - "href": "/en/api-reference/on-call/alerts/alert-write-merge", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Without `kind`, personal calendars are returned. `region.official.holiday` returns public holiday calendars, filtered to the caller's locale unless `no_locale` is `true`; use their `cal_id` in `extra_cal_ids`.\n- The list is not paginated; `total` equals the number of items.", + "href": "/en/api-reference/on-call/calendars/calendar-list", "metadata": { - "sidebarTitle": "Merge alerts into an incident" + "sidebarTitle": "List calendars" } }, "responses": { @@ -35218,7 +38016,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyObject" + "$ref": "#/components/schemas/CalendarListResponse" } } } @@ -35226,7 +38024,51 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "items": [ + { + "account_id": 2451002751131, + "team_id": 2477033058131, + "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg", + "cal_name": "Stock Exchange Calendar", + "description": "A stock market trading calendar example", + "timezone": "Asia/Shanghai", + "kind": "personal", + "workdays": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "created_at": 1702455630, + "updated_at": 1775529526, + "creator_id": 2476444212131, + "updated_by": 3790925372131, + "status": "enabled" + }, + { + "account_id": 2451002751131, + "team_id": 0, + "cal_id": "cal.VZYkchxJhGELSF4jzkUAud", + "cal_name": "HK Stock Exchange Calendar", + "description": "Hong Kong Stock Exchange trading days calendar", + "timezone": "Asia/Shanghai", + "kind": "personal", + "extra_cal_ids": [ + "zh-cn.china.official" + ], + "created_at": 1702968470, + "updated_at": 1775188967, + "creator_id": 2451002751131, + "updated_by": 3790925372131, + "status": "enabled" + } + ], + "total": 8 + } } } } @@ -35252,32 +38094,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertMergeRequest" + "$ref": "#/components/schemas/CalendarListRequest" }, "example": { - "alert_ids": [ - "663a1b2c3d4e5f6789abcdef" - ], - "incident_id": "663a000000000000deadbeef" + "kind": "personal" } } } } } }, - "/alert/pipeline/info": { + "/calendar/update": { "post": { - "operationId": "alert-read-pipeline-info", - "summary": "Get alert pipeline", - "description": "Return the alert processing pipeline configured for a specific integration.", + "operationId": "calendarUpdate", + "summary": "Update calendar", + "description": "Update a personal service calendar; only the fields you send are changed.", "tags": [ - "On-call/Alerts" + "On-call/Calendars" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- When the integration has no pipeline, the response carries only `request_id` and the `data` field is omitted.\n- `integration_id` may be any account-level or channel-owned integration of the account; an unknown ID returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- Send at least one field besides `cal_id`; otherwise the call returns `InvalidParameter`.\n- `workdays` and `extra_cal_ids` replace the stored lists when sent (an empty array clears them); `team_id: 0` removes the team.\n- `cal_name` must stay unique within the account.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- On success the response carries only `request_id`; the `data` field is omitted.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/calendar-update", "metadata": { - "sidebarTitle": "Get alert pipeline" + "sidebarTitle": "Update calendar" } }, "responses": { @@ -35294,46 +38133,14 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertPipelineItem" + "$ref": "#/components/schemas/CalendarEmptyObject" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "integration_id": 10001, - "rules": [ - { - "kind": "title_reset", - "if": [ - { - "key": "labels.env", - "oper": "IN", - "vals": [ - "prod" - ] - } - ], - "settings": { - "title": "[TPL]{{.Labels.service}} / {{.Labels.check}}" - } - }, - { - "kind": "severity_reset", - "if": null, - "settings": { - "severity": "Warning" - } - } - ], - "status": "enabled", - "creator_id": 80011, - "updated_by": 80011, - "created_at": 1710000000, - "updated_at": 1712000000 - } + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } } @@ -35359,29 +38166,38 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertPipelineInfoRequest" + "$ref": "#/components/schemas/CalendarUpdateRequest" }, "example": { - "integration_id": 10001 + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "cal_name": "Production On-Call Calendar (Updated)", + "timezone": "America/New_York", + "workdays": [ + 1, + 2, + 3, + 4, + 5 + ] } } } } } }, - "/alert/pipeline/list": { + "/change/list": { "post": { - "operationId": "alert-read-pipeline-list", - "summary": "List alert pipelines", - "description": "Return the alert processing pipelines configured for multiple integrations.", + "operationId": "change-read-list", + "summary": "List changes", + "description": "Query change records within a time window, with filtering, search, and pagination.", "tags": [ - "On-call/Alerts" + "On-call/Changes" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Every `integration_ids` entry must be an integration of the account; one unknown ID fails the whole request with `InvalidParameter`.\n- `items` holds one entry per integration that has a pipeline; integrations without one are absent.", - "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- `start_time` and `end_time` are both required: `start_time` must be less than `end_time`, and the window can span at most 31 days.\n- A change matches when its `[start_time, last_time]` range overlaps the query window.\n- Set `include_events` to `true` to attach each change's underlying events in `events`.", + "href": "/en/api-reference/on-call/changes/change-read-list", "metadata": { - "sidebarTitle": "List alert pipelines" + "sidebarTitle": "List changes" } }, "responses": { @@ -35398,7 +38214,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertPipelineListResponse" + "$ref": "#/components/schemas/ListChangeResponse" } } } @@ -35407,42 +38223,29 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { + "total": 1, + "has_next_page": false, "items": [ { - "integration_id": 10001, - "rules": [ - { - "kind": "alert_inhibit", - "if": [ - { - "key": "labels.cluster", - "oper": "IN", - "vals": [ - "prod-cn" - ] - } - ], - "settings": { - "equals": [ - "labels.service" - ], - "source_filters": [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Critical" - ] - } - ] - } - } - ], - "status": "enabled", - "creator_id": 80011, - "updated_by": 80011, - "created_at": 1710000000, - "updated_at": 1712000000 + "change_id": "664a1b2c3d4e5f6a7b8c9d0e", + "account_id": 10001, + "channel_id": 5001, + "channel_name": "Production", + "channel_status": "enabled", + "integration_id": 362, + "integration_name": "GitHub Deploy", + "title": "Deploy api-server v2.3.1", + "description": "Rolling deploy to production cluster", + "change_key": "deploy-api-server-2311", + "change_status": "Done", + "start_time": 1716962400, + "last_time": 1716962700, + "end_time": 1716963000, + "labels": { + "service": "api-server", + "env": "prod" + }, + "link": "https://github.com/acme/api-server/actions/runs/123" } ] } @@ -35471,32 +38274,38 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertPipelineListRequest" + "$ref": "#/components/schemas/ListChangeRequest" }, "example": { + "start_time": 1716960000, + "end_time": 1717046400, + "p": 1, + "limit": 10, "integration_ids": [ - 10001, - 10002 - ] + 362 + ], + "orderby": "start_time", + "asc": false, + "include_events": false } } } } } }, - "/alert/pipeline/upsert": { + "/channel/create": { "post": { - "operationId": "alert-write-pipeline-upsert", - "summary": "Create or update alert pipeline", - "description": "Set the alert processing pipeline for an integration. Replaces the existing configuration entirely.", + "operationId": "channelCreate", + "summary": "Create channel", + "description": "Create a channel, optionally with a default escalation rule and channel-exclusive integrations.", "tags": [ - "On-call/Alerts" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Replaces the integration's whole rule list with `rules`; an empty array removes every rule. At most 50 rules.\n- Rules run in array order on each incoming event of the integration before it becomes an alert; `alert_drop`, or an `alert_inhibit` that matches, discards the event and stops processing.\n- `integration_id` may be an account-level or a channel-owned integration; an ID not in the account returns `InvalidParameter`.\n- Write access also requires object permission: the account owner, an administrator, the integration creator, or a member of its team (for a channel-owned integration, a member of the channel's team); with no team, any caller with the API permission may write.\n- An `alert_inhibit` rule requires the Standard plan or higher; otherwise the call returns `NoLicense`.\n- On success the response carries only `request_id`; the `data` field is omitted.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/alerts/alert-write-pipeline-upsert", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- `channel_name` must be unique within the account; a duplicate returns `InvalidParameter`.\n- `group.method` `p` requires the Standard license or higher and `i` requires the Pro license. Creating a channel beyond the plan's channel quota also returns `NoLicense`.\n- When `escalate_rule` is set, an enabled escalation rule named `Default` is created with one level that notifies `escalate_rule.target` once.\n- Each ID in `plugin_ids` creates one channel-exclusive integration of that integration type, named after the type.\n- When `is_external_report_enabled` is `true`, the response also carries `external_report_token`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-create", "metadata": { - "sidebarTitle": "Create or update alert pipeline" + "sidebarTitle": "Create channel" } }, "responses": { @@ -35513,14 +38322,18 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ChannelCreateResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "channel_id": 6294542005131, + "channel_name": "Production Alerts" + } } } } @@ -35546,53 +38359,43 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertPipelineUpsertRequest" + "$ref": "#/components/schemas/CreateChannelRequest" }, "example": { - "integration_id": 10001, - "rules": [ - { - "kind": "title_reset", - "if": [ - { - "key": "labels.env", - "oper": "IN", - "vals": [ - "prod" - ] - } - ], - "settings": { - "title": "[TPL]{{.Labels.service}} / {{.Labels.check}}" - } - }, - { - "kind": "severity_reset", - "if": null, - "settings": { - "severity": "Warning" - } - } - ] + "team_id": 3521074710131, + "channel_name": "Production Alerts", + "description": "Handles all production environment alerts", + "group": { + "method": "p", + "equals": [ + [ + "labels.service" + ] + ], + "time_window": 10, + "window_type": "tumbling" + }, + "auto_resolve_timeout": 86400, + "auto_resolve_mode": "trigger" } } } } } }, - "/audit/operation/list": { + "/channel/delete": { "post": { - "operationId": "audit-read-operation-list", - "summary": "List auditable operation types", - "description": "Return all operation names that are recorded in the audit log, for use as `operations` filter values.", + "operationId": "channelDelete", + "summary": "Delete channel", + "description": "Delete a disabled channel together with its rules and channel-exclusive integrations.", "tags": [ - "Platform/Audit logs" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Use the `name` values from this response as `operations` filter values in `POST /audit/search`.\n- `name_cn` is the Chinese label shown in the console, returned in Chinese regardless of the request language; `name` is the stable value to filter on.", - "href": "/en/api-reference/platform/audit-logs/audit-read-operation-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` channel can be deleted; any other status returns `InvalidParameter`.\n- If a shared integration's routing rule still targets the channel (in a case or the default branch), the call returns HTTP 400 with `error.code` `ReferenceExist` and the referencing integrations in `data.refs`. Remove the channel from those routes with `POST /route/upsert` first.\n- All escalation, silence, drop, inhibit and subscribe rules of the channel and its channel-exclusive integrations are deleted. The channel itself is soft-deleted: `POST /channel/info` still returns it with `status` `deleted`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-delete", "metadata": { - "sidebarTitle": "List auditable operation types" + "sidebarTitle": "Delete channel" } }, "responses": { @@ -35609,7 +38412,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AuditOperationListResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -35617,22 +38420,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "name": "template:write:create", - "name_cn": "创建模板" - }, - { - "name": "template:write:delete", - "name_cn": "删除模板" - }, - { - "name": "incident:write:acknowledge", - "name_cn": "认领故障" - } - ] - } + "data": {} } } } @@ -35658,27 +38446,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AuditOperationListRequest" + "$ref": "#/components/schemas/ChannelIDRequest" }, - "example": {} + "example": { + "channel_id": 3521074710131 + } } } } } }, - "/audit/search": { + "/channel/disable": { "post": { - "operationId": "audit-read-search", - "summary": "Search audit logs", - "description": "Return a cursor-paginated list of audit log entries within a time range.", + "operationId": "channelDisable", + "summary": "Disable channel", + "description": "Disable a channel; while disabled it discards all incoming alert events.", "tags": [ - "Platform/Audit logs" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Time range is required. Maximum span is 90 days. Both `start_time` and `end_time` are Unix epoch **seconds**.\n- Use `search_after_ctx` from the previous response to fetch the next page. The token is opaque — do not construct it manually.\n- The retention window depends on the account's license. Queries beyond the retention boundary silently return an empty result rather than an error.\n- Pass an explicit `limit` (1–99) for predictable paging; when it is omitted or 0 the server chooses the page size, which may be the whole result set. Entries are returned newest first.", - "href": "/en/api-reference/platform/audit-logs/audit-read-search", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` channel can be disabled; any other status returns `InvalidParameter`.\n- Rules and integrations are kept. Alert processing may take up to about one minute to see the new status.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-disable", "metadata": { - "sidebarTitle": "Search audit logs" + "sidebarTitle": "Disable channel" } }, "responses": { @@ -35695,7 +38485,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AuditSearchResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -35703,29 +38493,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "total": 2, - "search_after_ctx": "", - "docs": [ - { - "created_at": 1712700123456, - "account_id": 10023, - "member_id": 80011, - "member_name": "Alice", - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "ip": "203.0.113.42", - "operation": "template:write:create", - "operation_name": "创建模板", - "body": "{\"template_name\":\"Prod default\"}", - "params": [], - "is_dangerous": false, - "is_write": true, - "principal_kind": "member", - "credential_type": "", - "credential_id": 0 - } - ] - } + "data": {} } } } @@ -35751,35 +38519,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AuditSearchRequest" + "$ref": "#/components/schemas/ChannelIDRequest" }, "example": { - "start_time": 1712620800, - "end_time": 1712707200, - "limit": 20, - "operations": [ - "template:write:create", - "template:write:delete" - ] + "channel_id": 3521074710131 } } } } } }, - "/calendar/create": { + "/channel/enable": { "post": { - "operationId": "calendarCreate", - "summary": "Create calendar", - "description": "Create a personal service calendar with its weekly workdays and linked holiday calendars.", + "operationId": "channelEnable", + "summary": "Enable channel", + "description": "Enable a disabled channel so it processes incoming alert events again.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- An account can hold at most 5 calendars: once it has 5, a create call by any member returns `InvalidParameter`.\n- `cal_name` must be unique within the account, `timezone` must be a valid IANA name, and a nonzero `team_id` must be a team of the account; otherwise the call returns `InvalidParameter`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/calendars/calendar-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` channel can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-enable", "metadata": { - "sidebarTitle": "Create calendar" + "sidebarTitle": "Enable channel" } }, "responses": { @@ -35796,7 +38558,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -35804,10 +38566,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "cal_name": "API Test Calendar" - } + "data": {} } } } @@ -35833,38 +38592,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarCreateRequest" + "$ref": "#/components/schemas/ChannelIDRequest" }, "example": { - "cal_name": "Production On-Call Calendar", - "description": "Calendar for production on-call team", - "timezone": "Asia/Shanghai", - "workdays": [ - 1, - 2, - 3, - 4, - 5 - ] + "channel_id": 3521074710131 } } } } } }, - "/calendar/delete": { + "/channel/escalate/rule/create": { "post": { - "operationId": "calendarDelete", - "summary": "Delete calendar", - "description": "Delete a personal service calendar and its events when no rule references it.", + "operationId": "channelEscalateRuleCreate", + "summary": "Create escalation rule", + "description": "Create an escalation rule that decides who is notified about a channel's incidents, and how.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- If escalation rules or silence rules still use the calendar, the call returns HTTP 400 with `error.code` = `ReferenceExist` and `data.refs` listing them.\n- The calendar's own events are deleted together with it.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/calendars/calendar-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Rules are evaluated in ascending `priority`. The first enabled rule whose `time_filters` and `filters` match a new incident takes it; later rules are skipped. Omit `priority` to place the rule after all existing ones.\n- `template_id` must be an existing notification template, every member in `person_ids` must exist and every team in `team_ids` must have members; otherwise `InvalidParameter`.\n- The new rule is `enabled`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-create", "metadata": { - "sidebarTitle": "Delete calendar" + "sidebarTitle": "Create escalation rule" } }, "responses": { @@ -35881,7 +38631,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -35889,7 +38639,10 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "rule_id": "69db2f72a0fe7db6448b1506", + "rule_name": "On-call escalation" + } } } } @@ -35915,29 +38668,48 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarIDRequest" + "$ref": "#/components/schemas/CreateEscalationRuleRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM" + "channel_id": 3521074710131, + "rule_name": "On-call escalation", + "template_id": "6321aad26c12104586a88916", + "description": "Notify primary on-call, then escalate to secondary after 30 minutes", + "layers": [ + { + "target": { + "person_ids": [ + 3790925372131 + ], + "by": { + "follow_preference": true + } + }, + "max_times": 3, + "notify_step": 10, + "escalate_window": 30, + "force_escalate": false + } + ] } } } } } }, - "/calendar/event/delete": { + "/channel/escalate/rule/delete": { "post": { - "operationId": "calEventDelete", - "summary": "Delete calendar event", - "description": "Delete one personal-calendar event by ID, or clear the calendar's own events from a date range.", + "operationId": "channelEscalateRuleDelete", + "summary": "Delete escalation rule", + "description": "Delete a disabled escalation rule so it no longer appears in the channel's rule list.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- Pass either `event_id`, or both `start_at` and `end_at` (dates in `YYYY-MM-DD`, covering [`start_at`, `end_at`)); any other combination returns `InvalidParameter`.\n- Cleared days fall back to the linked holiday calendars and the weekly workdays.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/calendars/cal-event-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- The rule is soft-deleted: it disappears from the list, but `POST /channel/escalate/rule/info` still returns it with `status` `deleted`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-delete", "metadata": { - "sidebarTitle": "Delete calendar event" + "sidebarTitle": "Delete escalation rule" } }, "responses": { @@ -35954,7 +38726,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -35988,30 +38760,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalEventIDRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4" + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/calendar/event/list": { + "/channel/escalate/rule/disable": { "post": { - "operationId": "calEventList", - "summary": "List calendar events", - "description": "Return a personal calendar's events for a year, month or day, plus the resolved state of each day.", + "operationId": "channelEscalateRuleDisable", + "summary": "Disable escalation rule", + "description": "Disable an escalation rule without deleting it.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- `year` defaults to the current year; without `month` the whole year is returned, and `day` requires `month`.\n- `items` merges the calendar's own events (`cale.*` IDs), one generated `non_work.YYYYMMDD` entry per non-working weekday when `workdays` is set, and the events of the linked holiday calendars; `total` counts all of them.\n- `days` gives the resolved state of every day in the scope.\n- Only personal calendars (`cal_id` starting with `cal.`) are supported; other IDs return `InvalidParameter`.", - "href": "/en/api-reference/on-call/calendars/cal-event-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- A disabled rule takes no new incidents, and incidents already assigned through it stop receiving its notifications and escalations.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-disable", "metadata": { - "sidebarTitle": "List calendar events" + "sidebarTitle": "Disable escalation rule" } }, "responses": { @@ -36028,7 +38800,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalEventListResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -36036,57 +38808,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "account_id": 2451002751131, - "creator_id": 2476444212131, - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", - "summary": "Test Holiday", - "description": "A test holiday event", - "start_at": "2026-05-01", - "end_at": "2026-05-02", - "is_off": true, - "created_at": 1775972034, - "updated_at": 1775972034 - }, - { - "account_id": 2451002751131, - "creator_id": 2451002751131, - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "event_id": "non_work.20260502", - "summary": "non-working day (Saturday)", - "description": "", - "start_at": "2026-05-02", - "end_at": "2026-05-03", - "is_off": true, - "created_at": 0, - "updated_at": 0 - } - ], - "total": 11, - "days": { - "2026-05-01": { - "is_off": true, - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", - "layer": "custom" - }, - "2026-05-02": { - "is_off": true, - "event_id": "non_work.20260502", - "layer": "weekly" - }, - "2026-05-09": { - "is_off": false, - "event_id": "zh-cn.china.official.c234057c-fd90-380e-889c-3e3254dd5b01", - "layer": "holiday" - }, - "2026-05-11": { - "is_off": false - } - } - } + "data": {} } } } @@ -36112,31 +38834,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalEventListRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "year": 2024, - "month": 5 + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/calendar/event/upsert": { + "/channel/escalate/rule/enable": { "post": { - "operationId": "calEventUpsert", - "summary": "Upsert calendar event", - "description": "Create or update one of a personal calendar's own events: a day off or a working-day override.", + "operationId": "channelEscalateRuleEnable", + "summary": "Enable escalation rule", + "description": "Enable a disabled escalation rule so it can take new incidents again.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- The event covers the days [`start_at`, `end_at`), dates in `YYYY-MM-DD`; `end_at` must be later than `start_at`.\n- Omit `event_id` to create an event; a given `event_id` must be an existing event of this calendar.\n- The write clears the calendar's other own events off the same days: an event fully inside the range is deleted, one partly inside is shortened, and one spanning the range is split in two, so the latest write decides those days.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/calendars/cal-event-upsert", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-enable", "metadata": { - "sidebarTitle": "Upsert calendar event" + "sidebarTitle": "Enable escalation rule" } }, "responses": { @@ -36153,7 +38874,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalEventUpsertResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -36161,11 +38882,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", - "summary": "Test Holiday" - } + "data": {} } } } @@ -36191,34 +38908,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalEventUpsertRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "summary": "Labour Day", - "start_at": "2024-05-01", - "end_at": "2024-05-06", - "is_off": true, - "description": "International Workers Day holiday" + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/calendar/info": { + "/channel/escalate/rule/info": { "post": { - "operationId": "calendarInfo", - "summary": "Get calendar info", - "description": "Return the details of one service calendar of the account by its ID.", + "operationId": "channelEscalateRuleInfo", + "summary": "Get escalation rule detail", + "description": "Return one escalation rule of a channel, including its levels, time windows and filters.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- An unknown `cal_id` returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/calendars/calendar-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- A deleted rule is still returned, with `status` `deleted`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-info", "metadata": { - "sidebarTitle": "Get calendar info" + "sidebarTitle": "Get escalation rule detail" } }, "responses": { @@ -36235,7 +38948,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarItem" + "$ref": "#/components/schemas/EscalateRuleItem" } } } @@ -36245,26 +38958,36 @@ "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "account_id": 2451002751131, - "team_id": 2477033058131, - "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg", - "cal_name": "Stock Exchange Calendar", - "description": "A stock market trading calendar example", - "timezone": "Asia/Shanghai", - "kind": "personal", - "workdays": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 + "channel_id": 6193426913131, + "priority": 0, + "aggr_window": 0, + "rule_name": "Default", + "description": "", + "layers": [ + { + "max_times": 1, + "notify_step": 10, + "target": { + "person_ids": [ + 3790925372131 + ], + "by": { + "follow_preference": true + }, + "webhooks": null + }, + "escalate_window": 30, + "force_escalate": false + } ], - "created_at": 1702455630, - "updated_at": 1775529526, - "creator_id": 2476444212131, + "time_filters": [], + "filters": [], + "status": "enabled", + "template_id": "6321aad26c12104586a88916", + "rule_id": "69bd0ce95a238693176c1d66", "updated_by": 3790925372131, - "status": "enabled" + "created_at": 1773997289, + "updated_at": 1773997289 } } } @@ -36291,29 +39014,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarIDRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg" + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34d0" } } } } } }, - "/calendar/list": { + "/channel/escalate/rule/list": { "post": { - "operationId": "calendarList", - "summary": "List calendars", - "description": "Return the list of service calendars visible to the current account.", + "operationId": "channelEscalateRuleList", + "summary": "List escalation rules", + "description": "List a channel's escalation rules in the order they are evaluated.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Without `kind`, personal calendars are returned. `region.official.holiday` returns public holiday calendars, filtered to the caller's locale unless `no_locale` is `true`; use their `cal_id` in `extra_cal_ids`.\n- The list is not paginated; `total` equals the number of items.", - "href": "/en/api-reference/on-call/calendars/calendar-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-list", "metadata": { - "sidebarTitle": "List calendars" + "sidebarTitle": "List escalation rules" } }, "responses": { @@ -36330,7 +39054,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarListResponse" + "$ref": "#/components/schemas/ListEscalationRulesResponse" } } } @@ -36342,46 +39066,38 @@ "items": [ { "account_id": 2451002751131, - "team_id": 2477033058131, - "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg", - "cal_name": "Stock Exchange Calendar", - "description": "A stock market trading calendar example", - "timezone": "Asia/Shanghai", - "kind": "personal", - "workdays": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6 - ], - "created_at": 1702455630, - "updated_at": 1775529526, - "creator_id": 2476444212131, - "updated_by": 3790925372131, - "status": "enabled" - }, - { - "account_id": 2451002751131, - "team_id": 0, - "cal_id": "cal.VZYkchxJhGELSF4jzkUAud", - "cal_name": "HK Stock Exchange Calendar", - "description": "Hong Kong Stock Exchange trading days calendar", - "timezone": "Asia/Shanghai", - "kind": "personal", - "extra_cal_ids": [ - "zh-cn.china.official" + "channel_id": 6193426913131, + "priority": 0, + "aggr_window": 0, + "rule_name": "Default", + "description": "", + "layers": [ + { + "max_times": 1, + "notify_step": 10, + "target": { + "person_ids": [ + 3790925372131 + ], + "by": { + "follow_preference": true + }, + "webhooks": null + }, + "escalate_window": 30, + "force_escalate": false + } ], - "created_at": 1702968470, - "updated_at": 1775188967, - "creator_id": 2451002751131, + "time_filters": [], + "filters": [], + "status": "enabled", + "template_id": "6321aad26c12104586a88916", + "rule_id": "69bd0ce95a238693176c1d66", "updated_by": 3790925372131, - "status": "enabled" + "created_at": 1773997289, + "updated_at": 1773997289 } - ], - "total": 8 + ] } } } @@ -36408,29 +39124,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarListRequest" + "$ref": "#/components/schemas/ChannelScopedListRequest" }, "example": { - "kind": "personal" + "channel_id": 1001 } } } } } }, - "/calendar/update": { + "/channel/escalate/rule/update": { "post": { - "operationId": "calendarUpdate", - "summary": "Update calendar", - "description": "Update a personal service calendar; only the fields you send are changed.", + "operationId": "channelEscalateRuleUpdate", + "summary": "Update escalation rule", + "description": "Replace the configuration of an existing escalation rule.", "tags": [ - "On-call/Calendars" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- Send at least one field besides `cal_id`; otherwise the call returns `InvalidParameter`.\n- `workdays` and `extra_cal_ids` replace the stored lists when sent (an empty array clears them); `team_id: 0` removes the team.\n- `cal_name` must stay unique within the account.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- On success the response carries only `request_id`; the `data` field is omitted.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/calendars/calendar-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: omitted `description`, `aggr_window`, `time_filters` and `filters` are reset to empty or `0`. Only `priority` keeps its current value when omitted.\n- Validation is the same as for create. The rule's `status` is not changed; use the enable and disable endpoints.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-update", "metadata": { - "sidebarTitle": "Update calendar" + "sidebarTitle": "Update escalation rule" } }, "responses": { @@ -36447,14 +39163,15 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/EmptyResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } } @@ -36480,18 +39197,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarUpdateRequest" + "$ref": "#/components/schemas/UpdateEscalationRuleRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "cal_name": "Production On-Call Calendar (Updated)", - "timezone": "America/New_York", - "workdays": [ - 1, - 2, - 3, - 4, - 5 + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34d0", + "template_id": "6621b23f4a2c5e0012ab34d1", + "rule_name": "Default escalation", + "layers": [ + { + "target": { + "person_ids": [ + 42 + ], + "by": { + "critical": [ + "voice" + ], + "warning": [ + "sms" + ] + } + } + } ] } } @@ -36499,19 +39227,19 @@ } } }, - "/change/list": { + "/channel/info": { "post": { - "operationId": "change-read-list", - "summary": "List changes", - "description": "Query change records within a time window, with filtering, search, and pagination.", + "operationId": "channelInfo", + "summary": "Get channel detail", + "description": "Return one channel's full configuration with counts of its active incidents from the last 30 days.", "tags": [ - "On-call/Changes" + "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- `start_time` and `end_time` are both required: `start_time` must be less than `end_time`, and the window can span at most 31 days.\n- A change matches when its `[start_time, last_time]` range overlaps the query window.\n- Set `include_events` to `true` to attach each change's underlying events in `events`.", - "href": "/en/api-reference/on-call/changes/change-read-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Deleted channels are still returned, with `status` `deleted`.\n- A private channel (`is_private: true`) returns `AccessDenied` unless the caller is the account owner or an admin, its creator, or a member of its owning or managing teams.\n- `team_name`, `creator_name` and `is_starred` are not returned here; use `POST /channel/list` for them.\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-info", "metadata": { - "sidebarTitle": "List changes" + "sidebarTitle": "Get channel detail" } }, "responses": { @@ -36528,7 +39256,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListChangeResponse" + "$ref": "#/components/schemas/ChannelItem" } } } @@ -36537,31 +39265,10 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 1, - "has_next_page": false, - "items": [ - { - "change_id": "664a1b2c3d4e5f6a7b8c9d0e", - "account_id": 10001, - "channel_id": 5001, - "channel_name": "Production", - "channel_status": "enabled", - "integration_id": 362, - "integration_name": "GitHub Deploy", - "title": "Deploy api-server v2.3.1", - "description": "Rolling deploy to production cluster", - "change_key": "deploy-api-server-2311", - "change_status": "Done", - "start_time": 1716962400, - "last_time": 1716962700, - "end_time": 1716963000, - "labels": { - "service": "api-server", - "env": "prod" - }, - "link": "https://github.com/acme/api-server/actions/runs/123" - } - ] + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled", + "team_id": 10 } } } @@ -36588,38 +39295,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListChangeRequest" + "$ref": "#/components/schemas/ChannelInfoRequest" }, "example": { - "start_time": 1716960000, - "end_time": 1717046400, - "p": 1, - "limit": 10, - "integration_ids": [ - 362 - ], - "orderby": "start_time", - "asc": false, - "include_events": false + "channel_id": 1001 } } } } } }, - "/channel/create": { + "/channel/infos": { "post": { - "operationId": "channelCreate", - "summary": "Create channel", - "description": "Create a channel, optionally with a default escalation rule and channel-exclusive integrations.", + "operationId": "channelInfos", + "summary": "Batch get channels", + "description": "Return the ID, name and status of up to 1,000 channels in one call.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- `channel_name` must be unique within the account; a duplicate returns `InvalidParameter`.\n- `group.method` `p` requires the Standard license or higher and `i` requires the Pro license. Creating a channel beyond the plan's channel quota also returns `NoLicense`.\n- When `escalate_rule` is set, an enabled escalation rule named `Default` is created with one level that notifies `escalate_rule.target` once.\n- Each ID in `plugin_ids` creates one channel-exclusive integration of that integration type, named after the type.\n- When `is_external_report_enabled` is `true`, the response also carries `external_report_token`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- IDs that do not exist are skipped. Deleted channels are included, with `status` `deleted`.\n- Items are ordered by channel creation, not by the order of `channel_ids`.\n- Private channels are included regardless of the caller's team membership.", + "href": "/en/api-reference/on-call/channels/channel-infos", "metadata": { - "sidebarTitle": "Create channel" + "sidebarTitle": "Batch get channels" } }, "responses": { @@ -36636,7 +39334,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelCreateResponse" + "$ref": "#/components/schemas/ChannelInfosResponse" } } } @@ -36645,8 +39343,13 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "channel_id": 6294542005131, - "channel_name": "Production Alerts" + "items": [ + { + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled" + } + ] } } } @@ -36673,43 +39376,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateChannelRequest" + "$ref": "#/components/schemas/ChannelInfosRequest" }, "example": { - "team_id": 3521074710131, - "channel_name": "Production Alerts", - "description": "Handles all production environment alerts", - "group": { - "method": "p", - "equals": [ - [ - "labels.service" - ] - ], - "time_window": 10, - "window_type": "tumbling" - }, - "auto_resolve_timeout": 86400, - "auto_resolve_mode": "trigger" + "channel_ids": [ + 1001, + 1002 + ] } } } } } }, - "/channel/delete": { + "/channel/inhibit/rule/create": { "post": { - "operationId": "channelDelete", - "summary": "Delete channel", - "description": "Delete a disabled channel together with its rules and channel-exclusive integrations.", + "operationId": "channelInhibitRuleCreate", + "summary": "Create inhibit rule", + "description": "Create an inhibit rule that mutes alert events while a related source alert is still active.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` channel can be deleted; any other status returns `InvalidParameter`.\n- If a shared integration's routing rule still targets the channel (in a case or the default branch), the call returns HTTP 400 with `error.code` `ReferenceExist` and the referencing integrations in `data.refs`. Remove the channel from those routes with `POST /route/upsert` first.\n- All escalation, silence, drop, inhibit and subscribe rules of the channel and its channel-exclusive integrations are deleted. The channel itself is soft-deleted: `POST /channel/info` still returns it with `status` `deleted`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Standard license or higher; otherwise the call returns `NoLicense`.\n- An incoming event is inhibited when it matches `target_filters` and the same channel has an active (not recovered) alert with a different `alert_key` that matches `source_filters`, started within the 10 minutes before the event, and has the same value for every key in `equals`.\n- The rule never fires when `equals` or `source_filters` is empty, or when the incoming event has no value for a label listed in `equals`.\n- Inhibit rules are checked after drop and silence rules; the first matching inhibit rule is applied.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-create", "metadata": { - "sidebarTitle": "Delete channel" + "sidebarTitle": "Create inhibit rule" } }, "responses": { @@ -36726,7 +39418,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -36734,7 +39426,10 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "rule_id": "69db2f69a0fe7db6448b1504", + "rule_name": "Suppress Info when Critical fires" + } } } } @@ -36760,29 +39455,58 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelIDRequest" + "$ref": "#/components/schemas/CreateInhibitRuleRequest" }, "example": { - "channel_id": 3521074710131 + "channel_id": 3521074710131, + "rule_name": "Suppress Info when Critical fires", + "description": "When a Critical alert fires, suppress matching Info alerts", + "equals": [ + "labels.cluster", + "labels.service" + ], + "source_filters": [ + [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Critical" + ] + } + ] + ], + "target_filters": [ + [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Info" + ] + } + ] + ], + "is_directly_discard": false } } } } } }, - "/channel/disable": { + "/channel/inhibit/rule/delete": { "post": { - "operationId": "channelDisable", - "summary": "Disable channel", - "description": "Disable a channel; while disabled it discards all incoming alert events.", + "operationId": "channelInhibitRuleDelete", + "summary": "Delete inhibit rule", + "description": "Delete a disabled inhibit rule so it no longer appears in the channel's rule list.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` channel can be disabled; any other status returns `InvalidParameter`.\n- Rules and integrations are kept. Alert processing may take up to about one minute to see the new status.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-disable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-delete", "metadata": { - "sidebarTitle": "Disable channel" + "sidebarTitle": "Delete inhibit rule" } }, "responses": { @@ -36833,29 +39557,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelIDRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_id": 3521074710131 + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/enable": { + "/channel/inhibit/rule/disable": { "post": { - "operationId": "channelEnable", - "summary": "Enable channel", - "description": "Enable a disabled channel so it processes incoming alert events again.", + "operationId": "channelInhibitRuleDisable", + "summary": "Disable inhibit rule", + "description": "Disable an inhibit rule without deleting it.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` channel can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-enable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-disable", "metadata": { - "sidebarTitle": "Enable channel" + "sidebarTitle": "Disable inhibit rule" } }, "responses": { @@ -36906,29 +39631,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelIDRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_id": 3521074710131 + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/escalate/rule/create": { + "/channel/inhibit/rule/enable": { "post": { - "operationId": "channelEscalateRuleCreate", - "summary": "Create escalation rule", - "description": "Create an escalation rule that decides who is notified about a channel's incidents, and how.", + "operationId": "channelInhibitRuleEnable", + "summary": "Enable inhibit rule", + "description": "Enable a disabled inhibit rule so it mutes matching alert events again.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Rules are evaluated in ascending `priority`. The first enabled rule whose `time_filters` and `filters` match a new incident takes it; later rules are skipped. Omit `priority` to place the rule after all existing ones.\n- `template_id` must be an existing notification template, every member in `person_ids` must exist and every team in `team_ids` must have members; otherwise `InvalidParameter`.\n- The new rule is `enabled`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Standard license or higher; otherwise the call returns `NoLicense`.\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-enable", "metadata": { - "sidebarTitle": "Create escalation rule" + "sidebarTitle": "Enable inhibit rule" } }, "responses": { @@ -36945,7 +39671,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -36953,10 +39679,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "rule_id": "69db2f72a0fe7db6448b1506", - "rule_name": "On-call escalation" - } + "data": {} } } } @@ -36982,48 +39705,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateEscalationRuleRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { "channel_id": 3521074710131, - "rule_name": "On-call escalation", - "template_id": "6321aad26c12104586a88916", - "description": "Notify primary on-call, then escalate to secondary after 30 minutes", - "layers": [ - { - "target": { - "person_ids": [ - 3790925372131 - ], - "by": { - "follow_preference": true - } - }, - "max_times": 3, - "notify_step": 10, - "escalate_window": 30, - "force_escalate": false - } - ] + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/escalate/rule/delete": { + "/channel/inhibit/rule/list": { "post": { - "operationId": "channelEscalateRuleDelete", - "summary": "Delete escalation rule", - "description": "Delete a disabled escalation rule so it no longer appears in the channel's rule list.", + "operationId": "channelInhibitRuleList", + "summary": "List inhibit rules", + "description": "List a channel's inhibit rules, oldest first.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- The rule is soft-deleted: it disappears from the list, but `POST /channel/escalate/rule/info` still returns it with `status` `deleted`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-list", "metadata": { - "sidebarTitle": "Delete escalation rule" + "sidebarTitle": "List inhibit rules" } }, "responses": { @@ -37040,7 +39745,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListInhibitRulesResponse" } } } @@ -37048,7 +39753,48 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "items": [ + { + "account_id": 2451002751131, + "channel_id": 5967964835131, + "rule_name": "Suppress downstream alerts", + "description": "", + "source_filters": [ + [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Critical" + ] + } + ] + ], + "target_filters": [ + [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Info" + ] + } + ] + ], + "equals": [ + "labels.cluster", + "labels.service" + ], + "is_directly_discard": false, + "status": "enabled", + "rule_id": "69bcc630b9e63df36603e425", + "updated_by": 3790925372131, + "created_at": 1773979184, + "updated_at": 1773979184 + } + ] + } } } } @@ -37074,30 +39820,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/ChannelScopedListRequest" }, "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "channel_id": 1001 } } } } } }, - "/channel/escalate/rule/disable": { + "/channel/inhibit/rule/update": { "post": { - "operationId": "channelEscalateRuleDisable", - "summary": "Disable escalation rule", - "description": "Disable an escalation rule without deleting it.", + "operationId": "channelInhibitRuleUpdate", + "summary": "Update inhibit rule", + "description": "Replace the configuration of an existing inhibit rule.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- A disabled rule takes no new incidents, and incidents already assigned through it stop receiving its notifications and escalations.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-disable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: omitted `source_filters` and `target_filters` become empty, an omitted `is_directly_discard` becomes `false`, and an omitted `description` becomes empty.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-update", "metadata": { - "sidebarTitle": "Disable escalation rule" + "sidebarTitle": "Update inhibit rule" } }, "responses": { @@ -37148,30 +39893,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/UpdateInhibitRuleRequest" }, "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34ce", + "rule_name": "Suppress downstream", + "equals": [ + "labels.cluster" + ] } } } } } }, - "/channel/escalate/rule/enable": { + "/channel/list": { "post": { - "operationId": "channelEscalateRuleEnable", - "summary": "Enable escalation rule", - "description": "Enable a disabled escalation rule so it can take new incidents again.", + "operationId": "channelList", + "summary": "List channels", + "description": "List the channels visible to the caller, with filters, sorting and pagination.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-enable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Without filters, every channel in the account is returned except private channels the caller cannot access. Deleted channels are never returned.\n- Setting both `is_my_team` and `is_my_starred` to `true` returns `InvalidParameter`. `is_my_managed` takes precedence over both. With `is_my_managed` or `is_my_team`, `team_ids` is ignored.\n- With `is_brief: true`, items carry only `channel_id`, `channel_name`, `description`, `status` and `is_starred`, and all matches are returned in one page.\n- Always pass `p`. When it is omitted the first page is returned, but `has_next_page` is then `true` whenever anything matches.", + "href": "/en/api-reference/on-call/channels/channel-list", "metadata": { - "sidebarTitle": "Enable escalation rule" + "sidebarTitle": "List channels" } }, "responses": { @@ -37188,7 +39937,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListChannelsResponse" } } } @@ -37196,7 +39945,17 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "total": 42, + "has_next_page": true, + "items": [ + { + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled" + } + ] + } } } } @@ -37222,30 +39981,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/ListChannelsRequest" }, "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "p": 1, + "limit": 20, + "orderby": "created_at", + "asc": false } } } } } }, - "/channel/escalate/rule/info": { + "/channel/silence/rule/create": { "post": { - "operationId": "channelEscalateRuleInfo", - "summary": "Get escalation rule detail", - "description": "Return one escalation rule of a channel, including its levels, time windows and filters.", + "operationId": "channelSilenceRuleCreate", + "summary": "Create silence rule", + "description": "Create a silence rule that mutes or drops matching alert events during a time window.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- A deleted rule is still returned, with `status` `deleted`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Set exactly one of `time_filter` (one-off window) or `time_filters` (recurring windows), and give `filters` at least one condition; otherwise `InvalidParameter`.\n- Each incoming event is checked against drop rules first, then silence rules, then inhibit rules. The first enabled silence rule whose window covers the current time and whose `filters` match is applied.\n- With `from_incident_id`, only one enabled silence rule may exist per incident; creating a second returns `InvalidParameter`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-create", "metadata": { - "sidebarTitle": "Get escalation rule detail" + "sidebarTitle": "Create silence rule" } }, "responses": { @@ -37262,7 +40023,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EscalateRuleItem" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -37271,37 +40032,8 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "account_id": 2451002751131, - "channel_id": 6193426913131, - "priority": 0, - "aggr_window": 0, - "rule_name": "Default", - "description": "", - "layers": [ - { - "max_times": 1, - "notify_step": 10, - "target": { - "person_ids": [ - 3790925372131 - ], - "by": { - "follow_preference": true - }, - "webhooks": null - }, - "escalate_window": 30, - "force_escalate": false - } - ], - "time_filters": [], - "filters": [], - "status": "enabled", - "template_id": "6321aad26c12104586a88916", - "rule_id": "69bd0ce95a238693176c1d66", - "updated_by": 3790925372131, - "created_at": 1773997289, - "updated_at": 1773997289 + "rule_id": "69db2f66a0fe7db6448b1503", + "rule_name": "Maintenance window silence" } } } @@ -37328,30 +40060,47 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/CreateSilenceRuleRequest" }, "example": { - "channel_id": 1001, - "rule_id": "6621b23f4a2c5e0012ab34d0" + "channel_id": 3521074710131, + "rule_name": "Maintenance window silence", + "description": "Silence all Info alerts during planned maintenance", + "time_filter": { + "start_time": 1773388800, + "end_time": 1773414000 + }, + "filters": [ + [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Info" + ] + } + ] + ], + "is_directly_discard": false } } } } } }, - "/channel/escalate/rule/list": { + "/channel/silence/rule/delete": { "post": { - "operationId": "channelEscalateRuleList", - "summary": "List escalation rules", - "description": "List a channel's escalation rules in the order they are evaluated.", + "operationId": "channelSilenceRuleDelete", + "summary": "Delete silence rule", + "description": "Delete a disabled silence rule so it no longer appears in the channel's rule list.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-delete", "metadata": { - "sidebarTitle": "List escalation rules" + "sidebarTitle": "Delete silence rule" } }, "responses": { @@ -37368,7 +40117,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListEscalationRulesResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -37376,43 +40125,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "account_id": 2451002751131, - "channel_id": 6193426913131, - "priority": 0, - "aggr_window": 0, - "rule_name": "Default", - "description": "", - "layers": [ - { - "max_times": 1, - "notify_step": 10, - "target": { - "person_ids": [ - 3790925372131 - ], - "by": { - "follow_preference": true - }, - "webhooks": null - }, - "escalate_window": 30, - "force_escalate": false - } - ], - "time_filters": [], - "filters": [], - "status": "enabled", - "template_id": "6321aad26c12104586a88916", - "rule_id": "69bd0ce95a238693176c1d66", - "updated_by": 3790925372131, - "created_at": 1773997289, - "updated_at": 1773997289 - } - ] - } + "data": {} } } } @@ -37438,29 +40151,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelScopedListRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_id": 1001 + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/escalate/rule/update": { + "/channel/silence/rule/disable": { "post": { - "operationId": "channelEscalateRuleUpdate", - "summary": "Update escalation rule", - "description": "Replace the configuration of an existing escalation rule.", + "operationId": "channelSilenceRuleDisable", + "summary": "Disable silence rule", + "description": "Disable a silence rule without deleting it.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: omitted `description`, `aggr_window`, `time_filters` and `filters` are reset to empty or `0`. Only `priority` keeps its current value when omitted.\n- Validation is the same as for create. The rule's `status` is not changed; use the enable and disable endpoints.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-disable", "metadata": { - "sidebarTitle": "Update escalation rule" + "sidebarTitle": "Disable silence rule" } }, "responses": { @@ -37511,49 +40225,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateEscalationRuleRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_id": 1001, - "rule_id": "6621b23f4a2c5e0012ab34d0", - "template_id": "6621b23f4a2c5e0012ab34d1", - "rule_name": "Default escalation", - "layers": [ - { - "target": { - "person_ids": [ - 42 - ], - "by": { - "critical": [ - "voice" - ], - "warning": [ - "sms" - ] - } - } - } - ] + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/info": { + "/channel/silence/rule/enable": { "post": { - "operationId": "channelInfo", - "summary": "Get channel detail", - "description": "Return one channel's full configuration with counts of its active incidents from the last 30 days.", + "operationId": "channelSilenceRuleEnable", + "summary": "Enable silence rule", + "description": "Enable a disabled silence rule so it silences matching alert events again.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Deleted channels are still returned, with `status` `deleted`.\n- A private channel (`is_private: true`) returns `AccessDenied` unless the caller is the account owner or an admin, its creator, or a member of its owning or managing teams.\n- `team_name`, `creator_name` and `is_starred` are not returned here; use `POST /channel/list` for them.\n- An unknown `channel_id` returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/channels/channel-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-enable", "metadata": { - "sidebarTitle": "Get channel detail" + "sidebarTitle": "Enable silence rule" } }, "responses": { @@ -37570,7 +40265,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelItem" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -37578,12 +40273,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled", - "team_id": 10 - } + "data": {} } } } @@ -37609,29 +40299,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelInfoRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_id": 1001 + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/infos": { + "/channel/silence/rule/list": { "post": { - "operationId": "channelInfos", - "summary": "Batch get channels", - "description": "Return the ID, name and status of up to 1,000 channels in one call.", + "operationId": "channelSilenceRuleList", + "summary": "List silence rules", + "description": "List a channel's silence rules and whether each one is in effect right now.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- IDs that do not exist are skipped. Deleted channels are included, with `status` `deleted`.\n- Items are ordered by channel creation, not by the order of `channel_ids`.\n- Private channels are included regardless of the caller's team membership.", - "href": "/en/api-reference/on-call/channels/channel-infos", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- Listing also permanently removes one-off-window rules that are due for automatic cleanup (see `is_auto_delete`), so they no longer appear. Rules with recurring `time_filters` are never removed this way.\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-list", "metadata": { - "sidebarTitle": "Batch get channels" + "sidebarTitle": "List silence rules" } }, "responses": { @@ -37648,7 +40339,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelInfosResponse" + "$ref": "#/components/schemas/ListSilenceRulesResponse" } } } @@ -37659,9 +40350,34 @@ "data": { "items": [ { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled" + "account_id": 2451002751131, + "channel_id": 5967964835131, + "rule_name": "Silence Info alerts", + "description": "", + "from_incident_id": "000000000000000000000000", + "time_filters": [], + "time_filter": { + "start_time": 1773388800, + "end_time": 1773414000 + }, + "filters": [ + [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Info" + ] + } + ] + ], + "is_directly_discard": true, + "status": "enabled", + "rule_id": "69b3c426b4a6f5abf1f54873", + "updated_by": 3790925372131, + "created_at": 1773388838, + "updated_at": 1773388838, + "is_effective": false } ] } @@ -37690,32 +40406,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelInfosRequest" + "$ref": "#/components/schemas/ChannelScopedListRequest" }, "example": { - "channel_ids": [ - 1001, - 1002 - ] + "channel_id": 1001 } } } } } }, - "/channel/inhibit/rule/create": { + "/channel/silence/rule/update": { "post": { - "operationId": "channelInhibitRuleCreate", - "summary": "Create inhibit rule", - "description": "Create an inhibit rule that mutes alert events while a related source alert is still active.", + "operationId": "channelSilenceRuleUpdate", + "summary": "Update silence rule", + "description": "Replace the configuration of an existing silence rule.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Standard license or higher; otherwise the call returns `NoLicense`.\n- An incoming event is inhibited when it matches `target_filters` and the same channel has an active (not recovered) alert with a different `alert_key` that matches `source_filters`, started within the 10 minutes before the event, and has the same value for every key in `equals`.\n- The rule never fires when `equals` or `source_filters` is empty, or when the incoming event has no value for a label listed in `equals`.\n- Inhibit rules are checked after drop and silence rules; the first matching inhibit rule is applied.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The same time window and `filters` requirements as create apply. Switching between `time_filter` and `time_filters` clears the other one.\n- `description`, `is_directly_discard` and `is_auto_delete` are always overwritten, so omitting them resets them to empty or `false`. `from_incident_id` cannot be changed.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-update", "metadata": { - "sidebarTitle": "Create inhibit rule" + "sidebarTitle": "Update silence rule" } }, "responses": { @@ -37732,7 +40445,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -37740,10 +40453,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "rule_id": "69db2f69a0fe7db6448b1504", - "rule_name": "Suppress Info when Critical fires" - } + "data": {} } } } @@ -37769,58 +40479,46 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateInhibitRuleRequest" + "$ref": "#/components/schemas/UpdateSilenceRuleRequest" }, "example": { - "channel_id": 3521074710131, - "rule_name": "Suppress Info when Critical fires", - "description": "When a Critical alert fires, suppress matching Info alerts", - "equals": [ - "labels.cluster", - "labels.service" - ], - "source_filters": [ - [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Critical" - ] - } - ] - ], - "target_filters": [ + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34cd", + "rule_name": "Mute during maintenance", + "time_filter": { + "start_time": 1710000000, + "end_time": 1710086400 + }, + "filters": [ [ { - "key": "severity", + "key": "labels.service", "oper": "IN", "vals": [ - "Info" + "billing" ] } ] - ], - "is_directly_discard": false + ] } } } } } }, - "/channel/inhibit/rule/delete": { + "/channel/unsubscribe/rule/create": { "post": { - "operationId": "channelInhibitRuleDelete", - "summary": "Delete inhibit rule", - "description": "Delete a disabled inhibit rule so it no longer appears in the channel's rule list.", + "operationId": "channelUnsubscribeRuleCreate", + "summary": "Create drop rule", + "description": "Create a drop rule that discards matching alert events before any alert or incident is created.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Drop rules are checked first, before silence and inhibit rules. An event matching any enabled drop rule is discarded: no alert, incident or notification is produced.\n- Without `filters`, or with an empty list, the rule matches nothing.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-create", "metadata": { - "sidebarTitle": "Delete inhibit rule" + "sidebarTitle": "Create drop rule" } }, "responses": { @@ -37837,7 +40535,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -37845,7 +40543,10 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "rule_id": "69db2f6ba0fe7db6448b1505", + "rule_name": "Drop test environment alerts" + } } } } @@ -37871,30 +40572,43 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/CreateDropRuleRequest" }, "example": { "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "rule_name": "Drop test environment alerts", + "description": "Discard all alerts from the test environment before they create incidents", + "filters": [ + [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "test", + "dev" + ] + } + ] + ] } } } } } }, - "/channel/inhibit/rule/disable": { + "/channel/unsubscribe/rule/delete": { "post": { - "operationId": "channelInhibitRuleDisable", - "summary": "Disable inhibit rule", - "description": "Disable an inhibit rule without deleting it.", + "operationId": "channelUnsubscribeRuleDelete", + "summary": "Delete drop rule", + "description": "Delete a disabled drop rule so it no longer appears in the channel's rule list.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-disable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-delete", "metadata": { - "sidebarTitle": "Disable inhibit rule" + "sidebarTitle": "Delete drop rule" } }, "responses": { @@ -37956,19 +40670,19 @@ } } }, - "/channel/inhibit/rule/enable": { + "/channel/unsubscribe/rule/disable": { "post": { - "operationId": "channelInhibitRuleEnable", - "summary": "Enable inhibit rule", - "description": "Enable a disabled inhibit rule so it mutes matching alert events again.", + "operationId": "channelUnsubscribeRuleDisable", + "summary": "Disable drop rule", + "description": "Disable a drop rule without deleting it.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Standard license or higher; otherwise the call returns `NoLicense`.\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-enable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-disable", "metadata": { - "sidebarTitle": "Enable inhibit rule" + "sidebarTitle": "Disable drop rule" } }, "responses": { @@ -38030,19 +40744,19 @@ } } }, - "/channel/inhibit/rule/list": { + "/channel/unsubscribe/rule/enable": { "post": { - "operationId": "channelInhibitRuleList", - "summary": "List inhibit rules", - "description": "List a channel's inhibit rules, oldest first.", + "operationId": "channelUnsubscribeRuleEnable", + "summary": "Enable drop rule", + "description": "Enable a disabled drop rule so it discards matching alert events again.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-enable", "metadata": { - "sidebarTitle": "List inhibit rules" + "sidebarTitle": "Enable drop rule" } }, "responses": { @@ -38059,7 +40773,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListInhibitRulesResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -38067,48 +40781,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "account_id": 2451002751131, - "channel_id": 5967964835131, - "rule_name": "Suppress downstream alerts", - "description": "", - "source_filters": [ - [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Critical" - ] - } - ] - ], - "target_filters": [ - [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Info" - ] - } - ] - ], - "equals": [ - "labels.cluster", - "labels.service" - ], - "is_directly_discard": false, - "status": "enabled", - "rule_id": "69bcc630b9e63df36603e425", - "updated_by": 3790925372131, - "created_at": 1773979184, - "updated_at": 1773979184 - } - ] - } + "data": {} } } } @@ -38134,29 +40807,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelScopedListRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_id": 1001 + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/inhibit/rule/update": { + "/channel/unsubscribe/rule/list": { "post": { - "operationId": "channelInhibitRuleUpdate", - "summary": "Update inhibit rule", - "description": "Replace the configuration of an existing inhibit rule.", + "operationId": "channelUnsubscribeRuleList", + "summary": "List drop rules", + "description": "List a channel's drop rules, oldest first.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: omitted `source_filters` and `target_filters` become empty, an omitted `is_directly_discard` becomes `false`, and an omitted `description` becomes empty.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-list", "metadata": { - "sidebarTitle": "Update inhibit rule" + "sidebarTitle": "List drop rules" } }, "responses": { @@ -38173,7 +40847,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListDropRulesResponse" } } } @@ -38181,7 +40855,32 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "items": [ + { + "account_id": 2451002751131, + "channel_id": 5967964835131, + "rule_name": "Drop test alerts", + "description": "", + "filters": [ + [ + { + "key": "data_source_id", + "oper": "IN", + "vals": [ + "6113996590131" + ] + } + ] + ], + "status": "enabled", + "rule_id": "69bcc530b9e63df36603e421", + "updated_by": 3790925372131, + "created_at": 1773978928, + "updated_at": 1773978928 + } + ] + } } } } @@ -38207,34 +40906,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateInhibitRuleRequest" + "$ref": "#/components/schemas/ChannelScopedListRequest" }, "example": { - "channel_id": 1001, - "rule_id": "6621b23f4a2c5e0012ab34ce", - "rule_name": "Suppress downstream", - "equals": [ - "labels.cluster" - ] + "channel_id": 1001 } } } } } }, - "/channel/list": { + "/channel/unsubscribe/rule/update": { "post": { - "operationId": "channelList", - "summary": "List channels", - "description": "List the channels visible to the caller, with filters, sorting and pagination.", + "operationId": "channelUnsubscribeRuleUpdate", + "summary": "Update drop rule", + "description": "Replace the name, description and conditions of an existing drop rule.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Without filters, every channel in the account is returned except private channels the caller cannot access. Deleted channels are never returned.\n- Setting both `is_my_team` and `is_my_starred` to `true` returns `InvalidParameter`. `is_my_managed` takes precedence over both. With `is_my_managed` or `is_my_team`, `team_ids` is ignored.\n- With `is_brief: true`, items carry only `channel_id`, `channel_name`, `description`, `status` and `is_starred`, and all matches are returned in one page.\n- Always pass `p`. When it is omitted the first page is returned, but `has_next_page` is then `true` whenever anything matches.", - "href": "/en/api-reference/on-call/channels/channel-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: an omitted `description` becomes empty, and an omitted `filters` clears all conditions so the rule matches nothing.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-update", "metadata": { - "sidebarTitle": "List channels" + "sidebarTitle": "Update drop rule" } }, "responses": { @@ -38251,7 +40945,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListChannelsResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -38259,17 +40953,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "total": 42, - "has_next_page": true, - "items": [ - { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled" - } - ] - } + "data": {} } } } @@ -38295,32 +40979,42 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListChannelsRequest" + "$ref": "#/components/schemas/UpdateDropRuleRequest" }, "example": { - "p": 1, - "limit": 20, - "orderby": "created_at", - "asc": false + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34cf", + "rule_name": "Drop test alerts", + "filters": [ + [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "test" + ] + } + ] + ] } } } } } }, - "/channel/silence/rule/create": { + "/channel/update": { "post": { - "operationId": "channelSilenceRuleCreate", - "summary": "Create silence rule", - "description": "Create a silence rule that mutes or drops matching alert events during a time window.", + "operationId": "channelUpdate", + "summary": "Update channel", + "description": "Update a channel's settings; only the fields present in the request are changed.", "tags": [ "On-call/Channels" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Set exactly one of `time_filter` (one-off window) or `time_filters` (recurring windows), and give `filters` at least one condition; otherwise `InvalidParameter`.\n- Each incoming event is checked against drop rules first, then silence rules, then inhibit rules. The first enabled silence rule whose window covers the current time and whose `filters` match is applied.\n- With `from_incident_id`, only one enabled silence rule may exist per incident; creating a second returns `InvalidParameter`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Omitted or `null` fields keep their current value. `group`, `flapping` and `event_group` each replace the whole stored object.\n- Pass `managing_team_ids: []` to remove all managing teams.\n- `auto_resolve_mode` is applied only together with `auto_resolve_timeout`; when `auto_resolve_timeout` is sent without `auto_resolve_mode`, the mode resets to `trigger`.\n- Setting `is_external_report_enabled` to `true` generates a new `external_report_token` on every call and the previous token stops working; `false` clears the token.\n- A `channel_name` used by another channel returns `InvalidParameter`; `group.method` `p` or `i` without the matching license returns `NoLicense`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-update", "metadata": { - "sidebarTitle": "Create silence rule" + "sidebarTitle": "Update channel" } }, "responses": { @@ -38337,7 +41031,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/UpdateChannelResponse" } } } @@ -38346,8 +41040,7 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "rule_id": "69db2f66a0fe7db6448b1503", - "rule_name": "Maintenance window silence" + "external_report_token": "" } } } @@ -38374,47 +41067,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateSilenceRuleRequest" + "$ref": "#/components/schemas/UpdateChannelRequest" }, "example": { "channel_id": 3521074710131, - "rule_name": "Maintenance window silence", - "description": "Silence all Info alerts during planned maintenance", - "time_filter": { - "start_time": 1773388800, - "end_time": 1773414000 - }, - "filters": [ - [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Info" - ] - } - ] - ], - "is_directly_discard": false + "channel_name": "Production Alerts (v2)", + "description": "Updated description" } } } } } }, - "/channel/silence/rule/delete": { + "/datasource/im/person/try-link": { "post": { - "operationId": "channelSilenceRuleDelete", - "summary": "Delete silence rule", - "description": "Delete a disabled silence rule so it no longer appears in the channel's rule list.", + "operationId": "datasourceImPersonTryLink", + "summary": "Attempt IM person linking", + "description": "Try to automatically link unbound members to their IM accounts for one integration.", "tags": [ - "On-call/Channels" + "On-call/Integrations" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Looks up every account member not yet linked to this integration's IM app by email and phone; only Feishu, DingTalk and WeCom integrations are supported, other types return `InvalidParameter`.\n- A disabled integration returns `InvalidParameter`.\n- Returns `RequestLocked` while another linking run for the same integration is in progress, and `InvalidParameter` when the IM platform refuses the lookup (missing contact permissions or rejected credentials).\n- `new_linked_person_ids` is an empty array when nobody could be newly linked.", + "href": "/en/api-reference/on-call/integrations/datasource-im-person-try-link", "metadata": { - "sidebarTitle": "Delete silence rule" + "sidebarTitle": "Attempt IM person linking" } }, "responses": { @@ -38431,7 +41108,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/TryLinkPersonResponse" } } } @@ -38439,7 +41116,13 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "new_linked_person_ids": [ + 5348648172131 + ], + "unmatched_count": 2, + "no_contact_count": 1 + } } } } @@ -38465,30 +41148,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/TryLinkPersonRequest" }, "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "integration_id": 6113996590131 } } } } } }, - "/channel/silence/rule/disable": { + "/datasource/im/war-room-enabled/list": { "post": { - "operationId": "channelSilenceRuleDisable", - "summary": "Disable silence rule", - "description": "Disable a silence rule without deleting it.", + "operationId": "im-war-room-enabled-list", + "summary": "List war-room-enabled IM integrations", + "description": "List IM integrations that have the war-room feature enabled for the account.", "tags": [ - "On-call/Channels" + "On-call/IM integrations" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-disable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Returns enabled and disabled Feishu, DingTalk, WeCom, Slack, and Microsoft Teams integrations whose settings have `war_room_enabled` set to `true`; deleted integrations are excluded.\n- Secret values inside `settings` are masked as `******`.", + "href": "/en/api-reference/on-call/integrations/im-war-room-enabled-list", "metadata": { - "sidebarTitle": "Disable silence rule" + "sidebarTitle": "List war-room-enabled IM integrations" } }, "responses": { @@ -38505,7 +41187,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListWarRoomEnabledResponse" } } } @@ -38513,7 +41195,35 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "items": [ + { + "data_source_id": 362, + "account_id": 10001, + "team_id": 0, + "plugin_id": 101, + "name": "Feishu Ops", + "status": "enabled", + "category": "im", + "plugin_type": "feishu_app", + "plugin_type_name": "Feishu", + "description": "Feishu war-room integration", + "integration_key": "ik_8f3a2b1c9d0e", + "ref_id": "", + "settings": { + "war_room_enabled": true + }, + "no_editable": false, + "creator_id": 20001, + "updated_by": 20001, + "created_at": 1716962400, + "updated_at": 1716962700, + "last_time": 0, + "exclusive_data_source_id": 0, + "integration_id": 362 + } + ] + } } } } @@ -38539,30 +41249,27 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "type": "object" }, - "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" - } + "example": {} } } } } }, - "/channel/silence/rule/enable": { + "/enrichment/info": { "post": { - "operationId": "channelSilenceRuleEnable", - "summary": "Enable silence rule", - "description": "Enable a disabled silence rule so it silences matching alert events again.", + "operationId": "enrichment-read-info", + "summary": "Get enrichment rules", + "description": "Return the enrichment rule set configured for a specific integration.", "tags": [ - "On-call/Channels" + "On-call/Alert enrichment" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-enable", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- `integration_id` must be an existing integration of the account; otherwise `InvalidParameter`.\n- Returns `data: null` when the integration has no rule set.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-info", "metadata": { - "sidebarTitle": "Enable silence rule" + "sidebarTitle": "Get enrichment rules" } }, "responses": { @@ -38579,7 +41286,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/EnrichmentItem" } } } @@ -38587,7 +41294,25 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "integration_id": 5001, + "rules": [ + { + "kind": "extraction", + "settings": { + "source_field": "labels.env", + "result_label": "environment", + "pattern": "^(prod|staging|dev).*$", + "override": true + } + } + ], + "status": "enabled", + "updated_by": 80011, + "creator_id": 80011, + "created_at": 1710000000, + "updated_at": 1710000000 + } } } } @@ -38613,30 +41338,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/EnrichmentInfoRequest" }, "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "integration_id": 5001 } } } } } }, - "/channel/silence/rule/list": { + "/enrichment/list": { "post": { - "operationId": "channelSilenceRuleList", - "summary": "List silence rules", - "description": "List a channel's silence rules and whether each one is in effect right now.", + "operationId": "enrichment-read-list", + "summary": "List enrichment rules", + "description": "Return the enrichment rule sets for a list of integration IDs.", "tags": [ - "On-call/Channels" + "On-call/Alert enrichment" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- Listing also permanently removes one-off-window rules that are due for automatic cleanup (see `is_auto_delete`), so they no longer appear. Rules with recurring `time_filters` are never removed this way.\n- An unknown `channel_id` returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Every ID must be an existing integration of the account; otherwise `InvalidParameter`.\n- Integrations that have no rule set are left out of `items`.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-list", "metadata": { - "sidebarTitle": "List silence rules" + "sidebarTitle": "List enrichment rules" } }, "responses": { @@ -38653,7 +41377,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListSilenceRulesResponse" + "$ref": "#/components/schemas/EnrichmentListResponse" } } } @@ -38664,34 +41388,13 @@ "data": { "items": [ { - "account_id": 2451002751131, - "channel_id": 5967964835131, - "rule_name": "Silence Info alerts", - "description": "", - "from_incident_id": "000000000000000000000000", - "time_filters": [], - "time_filter": { - "start_time": 1773388800, - "end_time": 1773414000 - }, - "filters": [ - [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Info" - ] - } - ] - ], - "is_directly_discard": true, + "integration_id": 5001, + "rules": [], "status": "enabled", - "rule_id": "69b3c426b4a6f5abf1f54873", - "updated_by": 3790925372131, - "created_at": 1773388838, - "updated_at": 1773388838, - "is_effective": false + "updated_by": 80011, + "creator_id": 80011, + "created_at": 1710000000, + "updated_at": 1710000000 } ] } @@ -38720,29 +41423,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelScopedListRequest" + "$ref": "#/components/schemas/EnrichmentListRequest" }, "example": { - "channel_id": 1001 + "integration_ids": [ + 5001, + 5002 + ] } } } } } }, - "/channel/silence/rule/update": { + "/enrichment/mapping/api/create": { "post": { - "operationId": "channelSilenceRuleUpdate", - "summary": "Update silence rule", - "description": "Replace the configuration of an existing silence rule.", + "operationId": "mapping-api-write-create", + "summary": "Create mapping API", + "description": "Register an external HTTP API that enrichment rules call to look up alert labels.", "tags": [ - "On-call/Channels" + "On-call/Alert enrichment" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The same time window and `filters` requirements as create apply. Switching between `time_filter` and `time_filters` clears the other one.\n- `description`, `is_directly_discard` and `is_auto_delete` are always overwritten, so omitting them resets them to empty or `false`. `from_incident_id` cannot be changed.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Mappings Manage** (`on-call`) |\n\n## Usage\n\n- An enrichment rule with `mapping_type` = `api` sends `POST ` with the configured `headers` and the JSON body `{\"result_label_keys\": [...], \"event\": {...}}` (the alert event). The API must answer HTTP 200 with `{\"result_labels\": {\"