diff --git a/api-reference/openapi.en.json b/api-reference/openapi.en.json index 6d90bfcb..6557ee4e 100644 --- a/api-reference/openapi.en.json +++ b/api-reference/openapi.en.json @@ -34535,6 +34535,1695 @@ "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. Always `bar`.", + "enum": [ + "bar" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Free-form display options stored with the panel; not validated.", + "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": 15, + "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. Must be non-empty with unique names; `frame_index` and `field_index` are not allowed.", + "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. At most 1024 characters.", + "type": "string" + }, + "value": { + "description": "Value substituted into the query, 1-1024 characters. Cannot be `$__all`.", + "type": "string" + } + }, + "required": [ + "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, 80-1200.", + "type": [ + "integer", + "null" + ], + "minimum": 80, + "maximum": 1200 + }, + "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. Always `custom`.", + "enum": [ + "custom" + ], + "type": "string" + }, + "name": { + "description": "Variable name, referenced as `${name}` in panel queries. 1–64 characters starting with a letter or underscore. `app` and names starting with `__` are reserved; names must be unique.", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + }, + "label": { + "description": "Label shown in the variable bar, 1-189 characters when set.", + "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.", + "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. A tab holds at most 30 panels and 100 queries, top panels and sections together.", + "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 created by the deletion. Pass it as `expected_revision` to restore the dashboard.", + "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. Panels in the same `top_panels` list or the same section must not overlap.", + "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": "Search text, at most 128 characters. Split on spaces; each word must appear in the title or the description.", + "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", + "description": "Required for every panel kind except `text`, which must omit it." + }, + "queries": { + "description": "Queries of the panel, each with a unique `ref_id`. `time_series` and `top_list` take 1-26 queries, `table`, `stat` and `bar` exactly 1, `text` none.", + "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. `${name}` must name a variable declared in the dashboard; formatters such as `${name:fmt}` and a bare `$name` are rejected.", + "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, 1-255 characters. Cannot be an event ID such as `session_id` or `view_id`. For a high-cardinality field, `agg` must be `count` or `sum`.", + "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": "Application the query reads: a concrete application ID, or `$app` to follow the application selected on the dashboard. Required, at most 64 characters. Saving fails if the application does not exist or you cannot read it.", + "maxLength": 64, + "type": "string" + } + }, + "required": [ + "scope", + "agg", + "application_id" + ], + "type": "object" + }, + "RumDashboardQueryVariable": { + "description": "Variable whose options are the values of a RUM field.", + "properties": { + "kind": { + "description": "Variable kind. Always `query`.", + "enum": [ + "query" + ], + "type": "string" + }, + "name": { + "description": "Variable name, referenced as `${name}` in panel queries. 1–64 characters starting with a letter or underscore. `app` and names starting with `__` are reserved; names must be unique.", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + }, + "label": { + "description": "Label shown in the variable bar, 1-189 characters when set. When omitted, the console shows the field's display name.", + "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`. Must be non-empty and unique, and none may equal `$__all`. With selection `mode` `single`, exactly one value.", + "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. Always `stat`.", + "enum": [ + "stat" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Free-form display options stored with the panel; not validated.", + "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": 15, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "value_fields": { + "description": "Field keys whose values are reduced into the displayed number. Must be non-empty with unique names; `frame_index` and `field_index` are not allowed.", + "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. At most 30 panels and 100 queries, top panels and sections together.", + "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. Always `table`.", + "enum": [ + "table" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Free-form display options stored with the panel; not validated.", + "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. Together with the `data_link`s in `column_options`, 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. Always `text`.", + "enum": [ + "text" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Free-form display options stored with the panel; not validated.", + "type": "object" + }, + "markdown": { + "description": "Markdown body, at most 64 KiB. Text panels take no datasource or query. Images, raw HTML and `${` templates are rejected; links must be HTTPS or start with `/`.", + "maxLength": 65536, + "type": "string" + } + }, + "required": [ + "kind", + "options", + "markdown" + ], + "type": "object" + }, + "RumDashboardThreshold": { + "description": "Warning/critical thresholds drawn on a numeric panel. At least one of `warning` and `critical` is required.", + "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. Always `time_series`.", + "enum": [ + "time_series" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Free-form display options stored with the panel; not validated.", + "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": 15, + "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. Always `top_list`.", + "enum": [ + "top_list" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "Free-form display options stored with the panel; not validated.", + "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": 15, + "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 created by the deletion. Pass it as `expected_revision` to restore the dashboard.", + "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": 15, + "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": { @@ -41853,19 +43542,507 @@ } } }, - "/incident/assign": { + "/incident/assign": { + "post": { + "operationId": "incidentAssign", + "summary": "Assign incident", + "description": "Reassign incidents to members or an escalation rule, replacing the current responders.", + "tags": [ + "On-call/Incidents" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Responders not in the new target are removed; responders who stay keep their acknowledgement. If none of the remaining responders has acknowledged, the incident returns to `Triggered`. Any snooze is cleared.\n- When `assigned_to` sets none of `person_ids`, `escalate_rule_id`, and `emails`, the server re-runs the channel's escalation rule matching instead.\n- Closed incidents are skipped without error.\n- The server fills `assigned_at`, `id`, and `escalate_rule_name`, and derives `type` when it is omitted.", + "href": "/en/api-reference/on-call/incidents/incident-assign", + "metadata": { + "sidebarTitle": "Assign incident" + } + }, + "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", + "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/AssignIncidentRequest" + }, + "example": { + "incident_id": "69da451ef77b1b51f40e83ee", + "assigned_to": { + "person_ids": [ + 2476444212131 + ], + "type": "assign" + } + } + } + } + } + } + }, + "/incident/comment": { + "post": { + "operationId": "incidentComment", + "summary": "Add comment to incident", + "description": "Add a text comment to the incident timeline.", + "tags": [ + "On-call/Incidents" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- To mention a member, embed a markdown link in `comment` in the form `[@Display Name](flashduty://ref/member/)`. Mentioned members receive a dedicated personal notification, which is not affected by `mute_reply`.\n- Plain `@name` text without the link syntax does not create a mention.\n- The server rewrites each mention's display label to the member's canonical name.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", + "href": "/en/api-reference/on-call/incidents/incident-comment", + "metadata": { + "sidebarTitle": "Add comment to incident" + } + }, + "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", + "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/CommentIncidentRequest" + }, + "example": { + "incident_ids": [ + "69da451ef77b1b51f40e83ee" + ], + "comment": "Root cause identified. [@Jane Doe](flashduty://ref/member/2476444212131) please verify the fix.", + "comment_type_id": "6a5895d672a064bc2d3ddfc2" + } + } + } + } + } + }, + "/incident/comment-type/create": { + "post": { + "operationId": "incidentCommentTypeCreate", + "summary": "Create a comment type", + "description": "Create a comment type that can be attached to incident comments.", + "tags": [ + "On-call/Incidents" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- The new type is appended to the end of the display ordering.\n- The name must be unique within the account (case-insensitive, after trimming whitespace).\n- An account can have at most 10 comment types.\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-comment-type-create", + "metadata": { + "sidebarTitle": "Create a comment type" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/CreateIncidentCommentTypeResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "comment_type_id": "6a5895d672a064bc2d3ddfc2", + "item": { + "comment_type_id": "6a5895d672a064bc2d3ddfc2", + "account_id": 2451002751131, + "name": "Key finding", + "color": "#30A46C", + "position": 3, + "creator_id": 5068740052131, + "updated_by": 5068740052131, + "created_at": 1784190422, + "updated_at": 1784190422 + } + } + } + } + } + }, + "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/CreateIncidentCommentTypeRequest" + }, + "example": { + "name": "Key finding", + "color": "#30A46C" + } + } + } + } + } + }, + "/incident/comment-type/delete": { + "post": { + "operationId": "incidentCommentTypeDelete", + "summary": "Delete a comment type", + "description": "Permanently delete a comment type; comments that used it keep their text but lose the label.", + "tags": [ + "On-call/Incidents" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Hard delete — the comment type is removed permanently and cannot be restored.\n- Existing comments that referenced the type lose the type label but are not otherwise affected.\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-comment-type-delete", + "metadata": { + "sidebarTitle": "Delete a comment type" + } + }, + "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", + "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/DeleteIncidentCommentTypeRequest" + }, + "example": { + "comment_type_id": "6a5895b572a064bc2d3ddfc0" + } + } + } + } + } + }, + "/incident/comment-type/list": { + "post": { + "operationId": "incidentCommentTypeList", + "summary": "List comment types", + "description": "Retrieve all comment types of the account, ordered by their display position.", + "tags": [ + "On-call/Incidents" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** (`on-call`) or **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Returns the full list in one call — there is no pagination.\n- An account can have at most 10 comment types.", + "href": "/en/api-reference/on-call/incidents/incident-comment-type-list", + "metadata": { + "sidebarTitle": "List comment types" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ListIncidentCommentTypesResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "comment_type_id": "6a5895d672a064bc2d3ddfc2", + "account_id": 2451002751131, + "name": "Key finding", + "color": "#30A46C", + "position": 1, + "creator_id": 5068740052131, + "updated_by": 5068740052131, + "created_at": 1784190422, + "updated_at": 1784207748 + }, + { + "comment_type_id": "6a5895b572a064bc2d3ddfc0", + "account_id": 2451002751131, + "name": "Hypothesis", + "color": "#998000", + "position": 2, + "creator_id": 5068740052131, + "updated_by": 3790925372131, + "created_at": 1784190389, + "updated_at": 1785141535 + } + ] + } + } + } + } + }, + "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/ListIncidentCommentTypesRequest" + }, + "example": {} + } + } + } + } + }, + "/incident/comment-type/reorder": { + "post": { + "operationId": "incidentCommentTypeReorder", + "summary": "Reorder comment types", + "description": "Set the display order of all comment types by passing every type ID in the desired order.", + "tags": [ + "On-call/Incidents" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Full-set reorder — `comment_type_ids` must contain every comment type of the account, each exactly once, in the desired order.\n- Positions are reassigned starting from 1: the first ID in the array becomes position 1.\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-comment-type-reorder", + "metadata": { + "sidebarTitle": "Reorder comment types" + } + }, + "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", + "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/ReorderIncidentCommentTypesRequest" + }, + "example": { + "comment_type_ids": [ + "6a5895b572a064bc2d3ddfc0", + "6a5895d672a064bc2d3ddfc2" + ] + } + } + } + } + } + }, + "/incident/comment-type/update": { "post": { - "operationId": "incidentAssign", - "summary": "Assign incident", - "description": "Reassign incidents to members or an escalation rule, replacing the current responders.", + "operationId": "incidentCommentTypeUpdate", + "summary": "Update a comment type", + "description": "Update the name and/or color of an existing account comment type.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Responders not in the new target are removed; responders who stay keep their acknowledgement. If none of the remaining responders has acknowledged, the incident returns to `Triggered`. Any snooze is cleared.\n- When `assigned_to` sets none of `person_ids`, `escalate_rule_id`, and `emails`, the server re-runs the channel's escalation rule matching instead.\n- Closed incidents are skipped without error.\n- The server fills `assigned_at`, `id`, and `escalate_rule_name`, and derives `type` when it is omitted.", - "href": "/en/api-reference/on-call/incidents/incident-assign", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Partial update — only the provided fields are changed, but at least one of `name` or `color` must be provided.\n- The name must remain unique within the account (case-insensitive, after trimming whitespace).\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-comment-type-update", "metadata": { - "sidebarTitle": "Assign incident" + "sidebarTitle": "Update a comment type" } }, "responses": { @@ -41916,35 +44093,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AssignIncidentRequest" + "$ref": "#/components/schemas/UpdateIncidentCommentTypeRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee", - "assigned_to": { - "person_ids": [ - 2476444212131 - ], - "type": "assign" - } + "comment_type_id": "6a5895b572a064bc2d3ddfc0", + "color": "#B7791F" } } } } } }, - "/incident/comment": { + "/incident/create": { "post": { - "operationId": "incidentComment", - "summary": "Add comment to incident", - "description": "Add a text comment to the incident timeline.", + "operationId": "incidentCreate", + "summary": "Create incident", + "description": "Manually create a new incident and assign responders.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- To mention a member, embed a markdown link in `comment` in the form `[@Display Name](flashduty://ref/member/)`. Mentioned members receive a dedicated personal notification, which is not affected by `mute_reply`.\n- Plain `@name` text without the link syntax does not create a mention.\n- The server rewrites each mention's display label to the member's canonical name.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", - "href": "/en/api-reference/on-call/incidents/incident-comment", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Without an account create form, only `incident_severity` is required.\n- When the account has a create form, `title` (non-blank), `channel_id` and `assigned_to` become required, `fields` may contain only custom fields visible in the form, and the form's required fields must be filled.\n- Images can be attached only when the create form contains an image-upload element (at most 10 images): send `multipart/form-data` with the JSON request in `data` and files in `images`; the whole request must not exceed 50 MiB.\n- Assignment runs after the incident is created. Without `assigned_to`, the channel's escalation rules decide; a standalone incident with no `assigned_to` gets no responders. If assignment fails (for example an out-of-range `layer_idx`), the incident is still created, without responders.", + "href": "/en/api-reference/on-call/incidents/incident-create", "metadata": { - "sidebarTitle": "Add comment to incident" + "sidebarTitle": "Create incident" } }, "responses": { @@ -41961,7 +44133,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/CreateIncidentResponse" } } } @@ -41969,7 +44141,10 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "incident_id": "69db2ef1a0fe7db6448b14f1", + "title": "API test incident for docs" + } } } } @@ -41995,33 +44170,63 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CommentIncidentRequest" + "$ref": "#/components/schemas/CreateIncidentRequest" }, "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee" + "incident_severity": "Critical", + "title": "Database connection timeout on prod-db-01", + "channel_id": 2551105804131, + "assigned_to": { + "person_ids": [ + 2476444212131 + ] + } + } + }, + "multipart/form-data": { + "schema": { + "type": "object", + "required": [ + "data" ], - "comment": "Root cause identified. [@Jane Doe](flashduty://ref/member/2476444212131) please verify the fix.", - "comment_type_id": "6a5895d672a064bc2d3ddfc2" + "properties": { + "data": { + "type": "string", + "description": "JSON-encoded CreateIncidentRequest payload." + }, + "images": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + }, + "description": "Image files attached to the new incident." + } + } + }, + "encoding": { + "data": { + "contentType": "application/json" + } } } } } } }, - "/incident/comment-type/create": { + "/incident/custom-action/do": { "post": { - "operationId": "incidentCommentTypeCreate", - "summary": "Create a comment type", - "description": "Create a comment type that can be attached to incident comments.", + "operationId": "incidentCustomActionDo", + "summary": "Execute custom action", + "description": "Execute a custom action configured for an incident.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- The new type is appended to the end of the display ordering.\n- The name must be unique within the account (case-insensitive, after trimming whitespace).\n- An account can have at most 10 comment types.\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-comment-type-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The integration must be an enabled custom action integration whose channels include the incident's channel; otherwise the call fails with `InvalidParameter`.\n- The server posts the incident payload to the action's URL with a 2-second timeout. If that request fails, the call still returns HTTP 200 with the error in `data.message`; on success `data` is `null`.\n- A successful run adds an `i_custom` timeline entry.", + "href": "/en/api-reference/on-call/incidents/incident-custom-action-do", "metadata": { - "sidebarTitle": "Create a comment type" + "sidebarTitle": "Execute custom action" } }, "responses": { @@ -42038,7 +44243,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CreateIncidentCommentTypeResponse" + "$ref": "#/components/schemas/DoIncidentCustomActionResponse" } } } @@ -42046,20 +44251,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "comment_type_id": "6a5895d672a064bc2d3ddfc2", - "item": { - "comment_type_id": "6a5895d672a064bc2d3ddfc2", - "account_id": 2451002751131, - "name": "Key finding", - "color": "#30A46C", - "position": 3, - "creator_id": 5068740052131, - "updated_by": 5068740052131, - "created_at": 1784190422, - "updated_at": 1784190422 - } - } + "data": null } } } @@ -42085,30 +44277,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateIncidentCommentTypeRequest" + "$ref": "#/components/schemas/DoIncidentCustomActionRequest" }, "example": { - "name": "Key finding", - "color": "#30A46C" + "incident_id": "69da451ef77b1b51f40e83ee", + "integration_id": 2490562293131 } } } } } }, - "/incident/comment-type/delete": { + "/incident/disable-merge": { "post": { - "operationId": "incidentCommentTypeDelete", - "summary": "Delete a comment type", - "description": "Permanently delete a comment type; comments that used it keep their text but lose the label.", + "operationId": "incidentDisableMerge", + "summary": "Disable incident merge", + "description": "Stop new alerts and events from being merged into the given incidents.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Hard delete — the comment type is removed permanently and cannot be restored.\n- Existing comments that referenced the type lose the type label but are not otherwise affected.\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-comment-type-delete", + "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- Later events no longer merge into the incidents' existing alerts, and alert grouping no longer adds new alerts to these incidents.\n- IDs that do not match an incident are ignored.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-disable-merge", "metadata": { - "sidebarTitle": "Delete a comment type" + "sidebarTitle": "Disable incident merge" } }, "responses": { @@ -42159,29 +44351,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeleteIncidentCommentTypeRequest" + "$ref": "#/components/schemas/DisableIncidentMergeRequest" }, "example": { - "comment_type_id": "6a5895b572a064bc2d3ddfc0" + "incident_ids": [ + "69da451ef77b1b51f40e83ee" + ] } } } } } }, - "/incident/comment-type/list": { + "/incident/feed": { "post": { - "operationId": "incidentCommentTypeList", - "summary": "List comment types", - "description": "Retrieve all comment types of the account, ordered by their display position.", + "operationId": "incidentFeed", + "summary": "Get incident timeline", + "description": "List an incident's timeline entries, such as state changes, assignments, notifications, comments, and work item events.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** (`on-call`) or **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Returns the full list in one call — there is no pagination.\n- An account can have at most 10 comment types.", - "href": "/en/api-reference/on-call/incidents/incident-comment-type-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- For `i_comm` entries, `detail.comment_type` is resolved from the current account-level comment type definition at read time, so it reflects the type's latest name and color.\n- Only entries recorded on the incident itself are returned; alert-level entries are read through the alert endpoints.\n- Entries are ordered by creation time, newest first unless `asc` is `true`. Paginate with `p` and `limit`; `has_next_page` tells whether another page exists, and no total count is returned.\n- For `i_notify` entries, `failed_reason` is a localized message describing a delivery failure, filled in at read time.", + "href": "/en/api-reference/on-call/incidents/incident-feed", "metadata": { - "sidebarTitle": "List comment types" + "sidebarTitle": "Get incident timeline" } }, "responses": { @@ -42198,7 +44392,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListIncidentCommentTypesResponse" + "$ref": "#/components/schemas/ListIncidentFeedResponse" } } } @@ -42207,28 +44401,59 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { + "has_next_page": true, "items": [ { - "comment_type_id": "6a5895d672a064bc2d3ddfc2", + "ref_id": "6a5f1e28807515413b384bce", + "type": "i_wi_created", + "detail": { + "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", + "item_type": "follow_up", + "title": "Follow-up: schedule database failover drill", + "status": "open", + "assignee_ids": [ + 3790925372131, + 4756301322131 + ], + "post_mortem_id": "51d65cd9525c369379ba471b5512df63" + }, "account_id": 2451002751131, - "name": "Key finding", - "color": "#30A46C", - "position": 1, - "creator_id": 5068740052131, - "updated_by": 5068740052131, - "created_at": 1784190422, - "updated_at": 1784207748 + "creator_id": 5329873302131, + "created_at": 1785495329402, + "updated_at": 1785495329402 }, { - "comment_type_id": "6a5895b572a064bc2d3ddfc0", + "ref_id": "6a5f1e28807515413b384bce", + "type": "i_comm", + "detail": { + "comment": "Root cause identified: connection pool exhaustion on the primary database.", + "comment_type_id": "6a5895d672a064bc2d3ddfc2", + "comment_type": { + "id": "6a5895d672a064bc2d3ddfc2", + "name": "Key finding", + "color": "#30A46C" + } + }, "account_id": 2451002751131, - "name": "Hypothesis", - "color": "#998000", - "position": 2, - "creator_id": 5068740052131, - "updated_by": 3790925372131, - "created_at": 1784190389, - "updated_at": 1785141535 + "creator_id": 3790925372131, + "created_at": 1785496333926, + "updated_at": 1785496333926 + }, + { + "ref_id": "6a5f1e28807515413b384bce", + "type": "i_wi_completed", + "detail": { + "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", + "item_type": "follow_up", + "title": "Follow-up: schedule database failover drill", + "from_status": "open", + "to_status": "done", + "post_mortem_id": "51d65cd9525c369379ba471b5512df63" + }, + "account_id": 2451002751131, + "creator_id": 3790925372131, + "created_at": 1785496384806, + "updated_at": 1785496384806 } ] } @@ -42257,27 +44482,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListIncidentCommentTypesRequest" + "$ref": "#/components/schemas/ListIncidentFeedRequest" }, - "example": {} + "example": { + "incident_id": "69da451ef77b1b51f40e83ee", + "p": 1, + "limit": 20 + } } } } } }, - "/incident/comment-type/reorder": { + "/incident/field/reset": { "post": { - "operationId": "incidentCommentTypeReorder", - "summary": "Reorder comment types", - "description": "Set the display order of all comment types by passing every type ID in the desired order.", + "operationId": "incidentFieldReset", + "summary": "Update incident custom field", + "description": "Update a custom field value on an incident.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Full-set reorder — `comment_type_ids` must contain every comment type of the account, each exactly once, in the desired order.\n- Positions are reassigned starting from 1: the first ID in the array becomes position 1.\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-comment-type-reorder", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The field must exist and be enabled on the account; `field_value` must match its type and options.\n- Omitting `field_value` or sending `null` clears the field on the incident.\n- If the value equals the current one, nothing changes.\n- A change adds a field-change entry to the incident timeline and triggers the same notifications and webhooks as a console edit.", + "href": "/en/api-reference/on-call/incidents/incident-field-reset", "metadata": { - "sidebarTitle": "Reorder comment types" + "sidebarTitle": "Update incident custom field" } }, "responses": { @@ -42328,32 +44557,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReorderIncidentCommentTypesRequest" + "$ref": "#/components/schemas/ResetIncidentFieldRequest" }, "example": { - "comment_type_ids": [ - "6a5895b572a064bc2d3ddfc0", - "6a5895d672a064bc2d3ddfc2" - ] + "incident_id": "69da451ef77b1b51f40e83ee", + "field_name": "affected_service", + "field_value": "payment-service" } } } } } }, - "/incident/comment-type/update": { + "/incident/info": { "post": { - "operationId": "incidentCommentTypeUpdate", - "summary": "Update a comment type", - "description": "Update the name and/or color of an existing account comment type.", + "operationId": "incidentInfo", + "summary": "Get incident detail", + "description": "Get one incident by ID or short number, with responders, assignment, custom fields, and alert counts.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Comment Types Manage** (`on-call`) |\n\n## Usage\n\n- Partial update — only the provided fields are changed, but at least one of `name` or `color` must be provided.\n- The name must remain unique within the account (case-insensitive, after trimming whitespace).\n- This permission is admin-only by default; custom roles must be granted it explicitly.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-comment-type-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- `num` is not unique; when several incidents share it, the most recent one is returned. Prefer `incident_id`.\n- This endpoint does not fill `alerts` or the `account_*` fields. Use `POST /incident/alert/list` for alerts and `POST /incident/feed` for the timeline.\n- Image tokens starting with `img_` in `images` are replaced with download URLs.\n- An unknown incident returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/incidents/incident-info", "metadata": { - "sidebarTitle": "Update a comment type" + "sidebarTitle": "Get incident detail" } }, "responses": { @@ -42370,7 +44598,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/IncidentInfo" } } } @@ -42378,7 +44606,86 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "incident_id": "69da451ef77b1b51f40e83ee", + "account_id": 2451002751131, + "channel_id": 2551105804131, + "team_id": 2477033058131, + "integration_id": 2490562293131, + "integration_ids": [ + 2490562293131 + ], + "integration_types": [ + "monit.alert" + ], + "dedup_key": "100128:prom-203.0.113.107:A:1579244238440766834:anydata", + "equals_md5": "", + "start_time": 1775912219, + "end_time": 0, + "last_time": 1775969819, + "ack_time": 0, + "close_time": 0, + "creator_id": 0, + "closer_id": 0, + "owner_id": 0, + "incident_status": "Critical", + "incident_severity": "Critical", + "progress": "Triggered", + "title": "CPU usage high - web-server-01", + "description": "", + "ai_summary": "", + "impact": "", + "root_cause": "", + "resolution": "", + "num": "0E83EE", + "frequency": "frequent", + "created_at": 1775912222, + "updated_at": 1775972145, + "snoozed_before": 0, + "group_method": "n", + "ever_muted": false, + "has_unfinished_work_item": false, + "labels": { + "check": "cpu_usage_high", + "resource": "web-server-01", + "env": "production" + }, + "fields": {}, + "assigned_to": { + "person_ids": [ + 2476444212131 + ], + "escalate_rule_id": "000000000000000000000000", + "layer_idx": 0, + "type": "assign", + "assigned_at": 1775972128, + "id": "MvQfH9Dc8eNS8k79jmrWn6", + "escalate_rule_name": "" + }, + "alert_cnt": 1, + "active_alert_cnt": 1, + "alert_event_cnt": 17, + "responders": [ + { + "person_id": 2476444212131, + "assigned_at": 1775972128, + "acknowledged_at": 0 + } + ], + "account_name": "", + "account_locale": "", + "account_time_zone": "", + "channel_name": "Ops Channel", + "channel_status": "enabled", + "detail_url": "https://app.flashcat.cloud/incident/detail/69da451ef77b1b51f40e83ee", + "silence_url": "https://app.flashcat.cloud/channel/detail/2551105804131?tab=alertSuppression&fromIncidentId=69da451ef77b1b51f40e83ee", + "integration_type": "monit.alert", + "post_mortem_id": "", + "images": null, + "manual_overrides": [ + "title" + ] + } } } } @@ -42404,30 +44711,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateIncidentCommentTypeRequest" + "$ref": "#/components/schemas/IncidentInfoRequest" }, "example": { - "comment_type_id": "6a5895b572a064bc2d3ddfc0", - "color": "#B7791F" + "incident_id": "69da451ef77b1b51f40e83ee" } } } } } }, - "/incident/create": { + "/incident/list": { "post": { - "operationId": "incidentCreate", - "summary": "Create incident", - "description": "Manually create a new incident and assign responders.", + "operationId": "incidentList", + "summary": "List incidents", + "description": "Query a paginated list of incidents with filters by channel, severity, status, responder, and time range.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Without an account create form, only `incident_severity` is required.\n- When the account has a create form, `title` (non-blank), `channel_id` and `assigned_to` become required, `fields` may contain only custom fields visible in the form, and the form's required fields must be filled.\n- Images can be attached only when the create form contains an image-upload element (at most 10 images): send `multipart/form-data` with the JSON request in `data` and files in `images`; the whole request must not exceed 50 MiB.\n- Assignment runs after the incident is created. Without `assigned_to`, the channel's escalation rules decide; a standalone incident with no `assigned_to` gets no responders. If assignment fails (for example an out-of-range `layer_idx`), the incident is still created, without responders.", - "href": "/en/api-reference/on-call/incidents/incident-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** or **Templates Read** or **Templates Manage** (`on-call`) |\n\n## Usage\n\n- Only incidents in channels the caller can access are returned.\n- `start_time` and `end_time` filter on incident start time and may span at most 31 days. A `start_time` earlier than the account's data retention period is moved up to the retention boundary; an `end_time` before that boundary fails with `InvalidParameter`.\n- Results are sorted by `start_time`, newest first unless `asc` is `true`.\n- Paginate with `p` and `limit`, or pass the previous response's `search_after_ctx`, in which case `p` is ignored.\n- `total` is capped at 1,000. `has_next_page` does not depend on `total`: with `p`/`limit` paging and in cursor mode alike it reflects whether more rows really exist, also past 1,000 incidents. Every non-empty page also returns `search_after_ctx` for cursor paging.\n- Without `progress`, incidents in every progress state are returned.", + "href": "/en/api-reference/on-call/incidents/incident-list", "metadata": { - "sidebarTitle": "Create incident" + "sidebarTitle": "List incidents" } }, "responses": { @@ -42444,7 +44750,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CreateIncidentResponse" + "$ref": "#/components/schemas/IncidentListResponse" } } } @@ -42453,8 +44759,91 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "incident_id": "69db2ef1a0fe7db6448b14f1", - "title": "API test incident for docs" + "total": 88, + "has_next_page": true, + "search_after_ctx": "69da451ef77b1b51f40e83eb", + "items": [ + { + "incident_id": "69da451ef77b1b51f40e83ee", + "account_id": 2451002751131, + "channel_id": 2551105804131, + "team_id": 2477033058131, + "integration_id": 2490562293131, + "integration_ids": [ + 2490562293131 + ], + "integration_types": [ + "monit.alert" + ], + "dedup_key": "100128:prom-203.0.113.107:A:1579244238440766834:anydata", + "equals_md5": "", + "start_time": 1775912219, + "end_time": 0, + "last_time": 1775969819, + "ack_time": 0, + "close_time": 0, + "creator_id": 0, + "closer_id": 0, + "owner_id": 0, + "incident_status": "Critical", + "incident_severity": "Critical", + "progress": "Triggered", + "title": "CPU usage high - web-server-01", + "description": "", + "ai_summary": "", + "impact": "", + "root_cause": "", + "resolution": "", + "num": "0E83EE", + "frequency": "frequent", + "created_at": 1775912222, + "updated_at": 1775972145, + "snoozed_before": 0, + "group_method": "n", + "ever_muted": false, + "has_unfinished_work_item": false, + "labels": { + "check": "cpu_usage_high", + "resource": "web-server-01", + "env": "production" + }, + "fields": {}, + "assigned_to": { + "person_ids": [ + 2476444212131 + ], + "escalate_rule_id": "000000000000000000000000", + "layer_idx": 0, + "type": "assign", + "assigned_at": 1775972128, + "id": "MvQfH9Dc8eNS8k79jmrWn6", + "escalate_rule_name": "" + }, + "alert_cnt": 1, + "active_alert_cnt": 1, + "alert_event_cnt": 17, + "responders": [ + { + "person_id": 2476444212131, + "assigned_at": 1775972128, + "acknowledged_at": 0 + } + ], + "account_name": "", + "account_locale": "", + "account_time_zone": "", + "channel_name": "Ops Channel", + "channel_status": "enabled", + "detail_url": "https://app.flashcat.cloud/incident/detail/69da451ef77b1b51f40e83ee", + "silence_url": "https://app.flashcat.cloud/channel/detail/2551105804131?tab=alertSuppression&fromIncidentId=69da451ef77b1b51f40e83ee", + "integration_type": "monit.alert", + "post_mortem_id": "", + "images": null, + "manual_overrides": [ + "title" + ] + } + ] } } } @@ -42481,63 +44870,37 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateIncidentRequest" + "$ref": "#/components/schemas/ListIncidentsRequest" }, "example": { - "incident_severity": "Critical", - "title": "Database connection timeout on prod-db-01", - "channel_id": 2551105804131, - "assigned_to": { - "person_ids": [ - 2476444212131 - ] - } - } - }, - "multipart/form-data": { - "schema": { - "type": "object", - "required": [ - "data" + "start_time": 1711900800, + "end_time": 1712000000, + "progress": "Triggered,Processing", + "incident_severity": "Critical,Warning", + "channel_ids": [ + 2551105804131 ], - "properties": { - "data": { - "type": "string", - "description": "JSON-encoded CreateIncidentRequest payload." - }, - "images": { - "type": "array", - "items": { - "type": "string", - "format": "binary" - }, - "description": "Image files attached to the new incident." - } - } - }, - "encoding": { - "data": { - "contentType": "application/json" - } + "limit": 20, + "p": 1 } } } } } }, - "/incident/custom-action/do": { + "/incident/list-by-ids": { "post": { - "operationId": "incidentCustomActionDo", - "summary": "Execute custom action", - "description": "Execute a custom action configured for an incident.", + "operationId": "incidentListByIds", + "summary": "List incidents by IDs", + "description": "Retrieve multiple incidents by their IDs in a single request.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The integration must be an enabled custom action integration whose channels include the incident's channel; otherwise the call fails with `InvalidParameter`.\n- The server posts the incident payload to the action's URL with a 2-second timeout. If that request fails, the call still returns HTTP 200 with the error in `data.message`; on success `data` is `null`.\n- A successful run adds an `i_custom` timeline entry.", - "href": "/en/api-reference/on-call/incidents/incident-custom-action-do", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** (`on-call`) |\n\n## Usage\n\n- IDs that do not match an incident are omitted; `total` is the number of incidents found and `has_next_page` is always `false`.\n- Results are sorted by `start_time`, newest first.\n- This endpoint does not fill `integration_type` or `assigned_to.escalate_rule_name`.", + "href": "/en/api-reference/on-call/incidents/incident-list-by-ids", "metadata": { - "sidebarTitle": "Execute custom action" + "sidebarTitle": "List incidents by IDs" } }, "responses": { @@ -42554,7 +44917,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/DoIncidentCustomActionResponse" + "$ref": "#/components/schemas/IncidentListResponse" } } } @@ -42562,7 +44925,77 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": null + "data": { + "total": 1, + "has_next_page": false, + "items": [ + { + "incident_id": "69da451ef77b1b51f40e83ee", + "account_id": 2451002751131, + "channel_id": 2551105804131, + "team_id": 2477033058131, + "integration_id": 2490562293131, + "integration_ids": [ + 2490562293131 + ], + "integration_types": [ + "monit.alert" + ], + "dedup_key": "100128:prom-203.0.113.107:A:1579244238440766834:anydata", + "equals_md5": "", + "start_time": 1775912219, + "end_time": 0, + "last_time": 1775969819, + "ack_time": 0, + "close_time": 0, + "creator_id": 0, + "closer_id": 0, + "owner_id": 0, + "incident_status": "Critical", + "incident_severity": "Critical", + "progress": "Triggered", + "title": "CPU usage high - web-server-01", + "description": "", + "ai_summary": "", + "impact": "", + "root_cause": "", + "resolution": "", + "num": "0E83EE", + "frequency": "frequent", + "created_at": 1775912222, + "updated_at": 1775972145, + "snoozed_before": 0, + "group_method": "n", + "ever_muted": false, + "has_unfinished_work_item": false, + "labels": {}, + "fields": {}, + "assigned_to": { + "escalate_rule_id": "000000000000000000000000", + "layer_idx": 0, + "type": "", + "assigned_at": 0, + "id": "", + "escalate_rule_name": "" + }, + "alert_cnt": 1, + "active_alert_cnt": 1, + "alert_event_cnt": 17, + "responders": [], + "account_name": "", + "account_locale": "", + "account_time_zone": "", + "channel_name": "Ops Channel", + "channel_status": "enabled", + "detail_url": "https://app.flashcat.cloud/incident/detail/69da451ef77b1b51f40e83ee", + "silence_url": "https://app.flashcat.cloud/channel/detail/2551105804131?tab=alertSuppression&fromIncidentId=69da451ef77b1b51f40e83ee", + "integration_type": "monit.alert", + "post_mortem_id": "", + "images": null, + "manual_overrides": null + } + ] + } } } } @@ -42588,30 +45021,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DoIncidentCustomActionRequest" + "$ref": "#/components/schemas/ListIncidentsByIdsRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee", - "integration_id": 2490562293131 + "incident_ids": [ + "69da451ef77b1b51f40e83ee", + "69da451ef77b1b51f40e83ef" + ] } } } } } }, - "/incident/disable-merge": { + "/incident/merge": { "post": { - "operationId": "incidentDisableMerge", - "summary": "Disable incident merge", - "description": "Stop new alerts and events from being merged into the given incidents.", + "operationId": "incidentMerge", + "summary": "Merge incidents", + "description": "Merge one or more incidents into a target incident.", "tags": [ "On-call/Incidents" ], "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- Later events no longer merge into the incidents' existing alerts, and alert grouping no longer adds new alerts to these incidents.\n- IDs that do not match an incident are ignored.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-disable-merge", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- All alerts of the source incidents move to the target incident, and the target gains the sources' integrations.\n- Source incidents that are still open are closed. With `remove_source_incidents: true` they are then permanently deleted; otherwise they stay closed with an `i_merge` timeline entry that points to the target.\n- The target's progress, responders, and assignment do not change; `title`, when set, replaces the target's title.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", + "href": "/en/api-reference/on-call/incidents/incident-merge", "metadata": { - "sidebarTitle": "Disable incident merge" + "sidebarTitle": "Merge incidents" } }, "responses": { @@ -42662,31 +45097,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DisableIncidentMergeRequest" + "$ref": "#/components/schemas/MergeIncidentsRequest" }, "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee" - ] + "source_incident_ids": [ + "69da451ef77b1b51f40e83ef", + "69da451ef77b1b51f40e83f0" + ], + "target_incident_id": "69da451ef77b1b51f40e83ee", + "comment": "Merging related database connectivity incidents into one." } } } } } }, - "/incident/feed": { + "/incident/past/list": { "post": { - "operationId": "incidentFeed", - "summary": "Get incident timeline", - "description": "List an incident's timeline entries, such as state changes, assignments, notifications, comments, and work item events.", + "operationId": "incidentPastList", + "summary": "List past incidents", + "description": "List closed incidents in the same channel that resemble a given incident, to reuse past root causes and resolutions.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- For `i_comm` entries, `detail.comment_type` is resolved from the current account-level comment type definition at read time, so it reflects the type's latest name and color.\n- Only entries recorded on the incident itself are returned; alert-level entries are read through the alert endpoints.\n- Entries are ordered by creation time, newest first unless `asc` is `true`. Paginate with `p` and `limit`; `has_next_page` tells whether another page exists, and no total count is returned.\n- For `i_notify` entries, `failed_reason` is a localized message describing a delivery failure, filled in at read time.", - "href": "/en/api-reference/on-call/incidents/incident-feed", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **5 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Professional edition or higher; otherwise the call fails with `NoLicense`.\n- Candidates are closed incidents in the same channel that started within the 30 days before the reference incident started and whose semantic similarity exceeds the channel's similarity threshold.\n- Results list incidents with longer `root_cause` plus `resolution` text first, then higher `score`, then more recent `start_time`.\n- `limit` defaults to 5 when omitted or `0`.\n- An empty `items` array means no similar incident was found, or the reference incident has not been indexed for similarity search yet.\n- The reference incident must belong to a channel; otherwise the call fails with `InvalidParameter`.", + "href": "/en/api-reference/on-call/incidents/incident-past-list", "metadata": { - "sidebarTitle": "Get incident timeline" + "sidebarTitle": "List past incidents" } }, "responses": { @@ -42703,7 +45141,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListIncidentFeedResponse" + "$ref": "#/components/schemas/ListPastIncidentsResponse" } } } @@ -42712,61 +45150,7 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "has_next_page": true, - "items": [ - { - "ref_id": "6a5f1e28807515413b384bce", - "type": "i_wi_created", - "detail": { - "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", - "item_type": "follow_up", - "title": "Follow-up: schedule database failover drill", - "status": "open", - "assignee_ids": [ - 3790925372131, - 4756301322131 - ], - "post_mortem_id": "51d65cd9525c369379ba471b5512df63" - }, - "account_id": 2451002751131, - "creator_id": 5329873302131, - "created_at": 1785495329402, - "updated_at": 1785495329402 - }, - { - "ref_id": "6a5f1e28807515413b384bce", - "type": "i_comm", - "detail": { - "comment": "Root cause identified: connection pool exhaustion on the primary database.", - "comment_type_id": "6a5895d672a064bc2d3ddfc2", - "comment_type": { - "id": "6a5895d672a064bc2d3ddfc2", - "name": "Key finding", - "color": "#30A46C" - } - }, - "account_id": 2451002751131, - "creator_id": 3790925372131, - "created_at": 1785496333926, - "updated_at": 1785496333926 - }, - { - "ref_id": "6a5f1e28807515413b384bce", - "type": "i_wi_completed", - "detail": { - "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", - "item_type": "follow_up", - "title": "Follow-up: schedule database failover drill", - "from_status": "open", - "to_status": "done", - "post_mortem_id": "51d65cd9525c369379ba471b5512df63" - }, - "account_id": 2451002751131, - "creator_id": 3790925372131, - "created_at": 1785496384806, - "updated_at": 1785496384806 - } - ] + "items": [] } } } @@ -42793,31 +45177,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListIncidentFeedRequest" + "$ref": "#/components/schemas/ListPastIncidentsRequest" }, "example": { "incident_id": "69da451ef77b1b51f40e83ee", - "p": 1, - "limit": 20 + "limit": 5 } } } } } }, - "/incident/field/reset": { + "/incident/post-mortem/basics/reset": { "post": { - "operationId": "incidentFieldReset", - "summary": "Update incident custom field", - "description": "Update a custom field value on an incident.", + "operationId": "postmortem-write-reset-basics", + "summary": "Update post-mortem basics", + "description": "Overwrite the incident facts (severity, times, responders) stored on a post-mortem report.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The field must exist and be enabled on the account; `field_value` must match its type and options.\n- Omitting `field_value` or sending `null` clears the field on the incident.\n- If the value equals the current one, nothing changes.\n- A change adds a field-change entry to the incident timeline and triggers the same notifications and webhooks as a console edit.", - "href": "/en/api-reference/on-call/incidents/incident-field-reset", + "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- Full overwrite: omitted `incidents_latest_close_seconds` and `incidents_total_duration_seconds` become 0, and omitted `responder_ids` clears the responders.\n- IDs in `responder_ids` that do not resolve to a person are dropped; each stored responder gets the current time as `assigned_at` and `acknowledged_at` = 0.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-basics", "metadata": { - "sidebarTitle": "Update incident custom field" + "sidebarTitle": "Update post-mortem basics" } }, "responses": { @@ -42841,8 +45224,7 @@ ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } } @@ -42868,31 +45250,36 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResetIncidentFieldRequest" + "$ref": "#/components/schemas/ResetPostMortemBasicsRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee", - "field_name": "affected_service", - "field_value": "payment-service" + "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", + "incidents_highest_severity": "Critical", + "incidents_earliest_start_seconds": 1773890000, + "incidents_latest_close_seconds": 1773897200, + "incidents_total_duration_seconds": 7200, + "responder_ids": [ + 3790925372131 + ] } } } } } }, - "/incident/info": { + "/incident/post-mortem/content/reset": { "post": { - "operationId": "incidentInfo", - "summary": "Get incident detail", - "description": "Get one incident by ID or short number, with responders, assignment, custom fields, and alert counts.", + "operationId": "incident-post-mortem-write-reset-content", + "summary": "Reset post-mortem content", + "description": "Replace the body of a drafting post-mortem report with Markdown.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- `num` is not unique; when several incidents share it, the most recent one is returned. Prefer `incident_id`.\n- This endpoint does not fill `alerts` or the `account_*` fields. Use `POST /incident/alert/list` for alerts and `POST /incident/feed` for the timeline.\n- Image tokens starting with `img_` in `images` are replaced with download URLs.\n- An unknown incident returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/incidents/incident-info", + "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- The report must be drafting and its current revision must equal `expected_revision`; otherwise the API returns `409 Conflict`.\n- Reuse an `idempotency_key` only for the same report, revision, and Markdown content; different reuse returns `409 Conflict`.\n- While another reset of the same report is still running, the call returns `RequestTooFrequently`; retry later.\n- A successful reset disconnects the previous collaboration (Yjs) room. Reconnect to the new generation room `post-mortem-{accountId}-{postMortemId}-g{N}` (generation 0 has no `-g` suffix). The reset cannot be rolled back.\n- Markdown content is limited to 4 MiB.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-post-mortem-write-reset-content", "metadata": { - "sidebarTitle": "Get incident detail" + "sidebarTitle": "Reset post-mortem content" } }, "responses": { @@ -42909,7 +45296,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/IncidentInfo" + "$ref": "#/components/schemas/PostMortemContentResetResponse" } } } @@ -42918,84 +45305,13 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "incident_id": "69da451ef77b1b51f40e83ee", - "account_id": 2451002751131, - "channel_id": 2551105804131, - "team_id": 2477033058131, - "integration_id": 2490562293131, - "integration_ids": [ - 2490562293131 - ], - "integration_types": [ - "monit.alert" - ], - "dedup_key": "100128:prom-203.0.113.107:A:1579244238440766834:anydata", - "equals_md5": "", - "start_time": 1775912219, - "end_time": 0, - "last_time": 1775969819, - "ack_time": 0, - "close_time": 0, - "creator_id": 0, - "closer_id": 0, - "owner_id": 0, - "incident_status": "Critical", - "incident_severity": "Critical", - "progress": "Triggered", - "title": "CPU usage high - web-server-01", - "description": "", - "ai_summary": "", - "impact": "", - "root_cause": "", - "resolution": "", - "num": "0E83EE", - "frequency": "frequent", - "created_at": 1775912222, - "updated_at": 1775972145, - "snoozed_before": 0, - "group_method": "n", - "ever_muted": false, - "has_unfinished_work_item": false, - "labels": { - "check": "cpu_usage_high", - "resource": "web-server-01", - "env": "production" - }, - "fields": {}, - "assigned_to": { - "person_ids": [ - 2476444212131 - ], - "escalate_rule_id": "000000000000000000000000", - "layer_idx": 0, - "type": "assign", - "assigned_at": 1775972128, - "id": "MvQfH9Dc8eNS8k79jmrWn6", - "escalate_rule_name": "" - }, - "alert_cnt": 1, - "active_alert_cnt": 1, - "alert_event_cnt": 17, - "responders": [ - { - "person_id": 2476444212131, - "assigned_at": 1775972128, - "acknowledged_at": 0 - } - ], - "account_name": "", - "account_locale": "", - "account_time_zone": "", - "channel_name": "Ops Channel", - "channel_status": "enabled", - "detail_url": "https://app.flashcat.cloud/incident/detail/69da451ef77b1b51f40e83ee", - "silence_url": "https://app.flashcat.cloud/channel/detail/2551105804131?tab=alertSuppression&fromIncidentId=69da451ef77b1b51f40e83ee", - "integration_type": "monit.alert", - "post_mortem_id": "", - "images": null, - "manual_overrides": [ - "title" - ] + "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", + "generation": 2, + "revision": 12, + "previous_generation": 1, + "previous_revision": 11, + "markdown_bytes": 88, + "markdown_sha256": "70d764e77e68f8fbfa14d72a235ac07b0110768b8380c8e3436459ebaf02a7c0" } } } @@ -43010,6 +45326,67 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "409": { + "description": "The report is not drafting, the revision is stale, or the idempotency key was reused for a different request.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "request_id", + "error" + ], + "properties": { + "request_id": { + "type": "string" + }, + "error": { + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "Conflict" + ] + }, + "message": { + "type": "string" + } + } + } + } + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "error": { + "code": "Conflict", + "message": "expected_revision conflict: request has 11 but current revision is 12" + } + } + } + } + }, + "413": { + "description": "Markdown content exceeds the 4 MiB limit.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "error": { + "code": "EntityTooLarge", + "message": "markdown exceeds maximum size" + } + } + } + } + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -43022,29 +45399,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IncidentInfoRequest" + "$ref": "#/components/schemas/ResetPostMortemContentRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee" + "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", + "markdown": "# Database saturation incident\n\nThe database pool was exhausted; added saturation alert.", + "expected_revision": 11, + "idempotency_key": "postmortem-reset-d3c9a7f2-11" } } } } } }, - "/incident/list": { + "/incident/post-mortem/delete": { "post": { - "operationId": "incidentList", - "summary": "List incidents", - "description": "Query a paginated list of incidents with filters by channel, severity, status, responder, and time range.", + "operationId": "incidentPostMortemDelete", + "summary": "Delete post-mortem", + "description": "Permanently delete a post-mortem report together with its uploaded media.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** or **Templates Read** or **Templates Manage** (`on-call`) |\n\n## Usage\n\n- Only incidents in channels the caller can access are returned.\n- `start_time` and `end_time` filter on incident start time and may span at most 31 days. A `start_time` earlier than the account's data retention period is moved up to the retention boundary; an `end_time` before that boundary fails with `InvalidParameter`.\n- Results are sorted by `start_time`, newest first unless `asc` is `true`.\n- Paginate with `p` and `limit`, or pass the previous response's `search_after_ctx`, in which case `p` is ignored.\n- `total` is capped at 1,000. `has_next_page` does not depend on `total`: with `p`/`limit` paging and in cursor mode alike it reflects whether more rows really exist, also past 1,000 incidents. Every non-empty page also returns `search_after_ctx` for cursor paging.\n- Without `progress`, incidents in every progress state are returned.", - "href": "/en/api-reference/on-call/incidents/incident-list", + "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- Requires the Professional edition or higher; otherwise the call fails with `NoLicense`.\n- The caller must be an account owner or admin, or a member of the post-mortem's team; otherwise the call fails with `AccessDenied`.\n- Linked incidents are unlinked, so their `post_mortem_id` becomes empty.\n- An unknown `post_mortem_id` returns `ResourceNotFound`.\n- On success the response has no `data` field.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-post-mortem-delete", "metadata": { - "sidebarTitle": "List incidents" + "sidebarTitle": "Delete post-mortem" } }, "responses": { @@ -43061,101 +45441,86 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/IncidentListResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "total": 88, - "has_next_page": true, - "search_after_ctx": "69da451ef77b1b51f40e83eb", - "items": [ - { - "incident_id": "69da451ef77b1b51f40e83ee", - "account_id": 2451002751131, - "channel_id": 2551105804131, - "team_id": 2477033058131, - "integration_id": 2490562293131, - "integration_ids": [ - 2490562293131 - ], - "integration_types": [ - "monit.alert" - ], - "dedup_key": "100128:prom-203.0.113.107:A:1579244238440766834:anydata", - "equals_md5": "", - "start_time": 1775912219, - "end_time": 0, - "last_time": 1775969819, - "ack_time": 0, - "close_time": 0, - "creator_id": 0, - "closer_id": 0, - "owner_id": 0, - "incident_status": "Critical", - "incident_severity": "Critical", - "progress": "Triggered", - "title": "CPU usage high - web-server-01", - "description": "", - "ai_summary": "", - "impact": "", - "root_cause": "", - "resolution": "", - "num": "0E83EE", - "frequency": "frequent", - "created_at": 1775912222, - "updated_at": 1775972145, - "snoozed_before": 0, - "group_method": "n", - "ever_muted": false, - "has_unfinished_work_item": false, - "labels": { - "check": "cpu_usage_high", - "resource": "web-server-01", - "env": "production" - }, - "fields": {}, - "assigned_to": { - "person_ids": [ - 2476444212131 - ], - "escalate_rule_id": "000000000000000000000000", - "layer_idx": 0, - "type": "assign", - "assigned_at": 1775972128, - "id": "MvQfH9Dc8eNS8k79jmrWn6", - "escalate_rule_name": "" - }, - "alert_cnt": 1, - "active_alert_cnt": 1, - "alert_event_cnt": 17, - "responders": [ - { - "person_id": 2476444212131, - "assigned_at": 1775972128, - "acknowledged_at": 0 - } - ], - "account_name": "", - "account_locale": "", - "account_time_zone": "", - "channel_name": "Ops Channel", - "channel_status": "enabled", - "detail_url": "https://app.flashcat.cloud/incident/detail/69da451ef77b1b51f40e83ee", - "silence_url": "https://app.flashcat.cloud/channel/detail/2551105804131?tab=alertSuppression&fromIncidentId=69da451ef77b1b51f40e83ee", - "integration_type": "monit.alert", - "post_mortem_id": "", - "images": null, - "manual_overrides": [ - "title" - ] + "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": { + "$ref": "#/components/schemas/DeletePostMortemRequest" + }, + "example": { + "post_mortem_id": "8104935102bf89dc01ac638a5261fe7e" + } + } + } + } + } + }, + "/incident/post-mortem/follow-ups/reset": { + "post": { + "operationId": "postmortem-write-reset-follow-ups", + "summary": "Update post-mortem follow-ups", + "description": "Replace the free-text follow-ups string stored on a post-mortem report.", + "tags": [ + "On-call/Incidents" + ], + "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- Works in any report status. Omitting `follow_ups` or sending `\"\"` clears the string.\n- When `follow_ups` is a JSON array in the console's follow-up format, its entries are also synced into structured follow-up work items (`source_kind` = `legacy_follow_up`); other text leaves the structured items unchanged.\n- To manage individual follow-ups, prefer the `/incident/work-item/*` endpoints.\n- The caller is added to the report's `author_ids`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-follow-ups", + "metadata": { + "sidebarTitle": "Update post-mortem follow-ups" + } + }, + "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" } } } @@ -43181,37 +45546,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListIncidentsRequest" + "$ref": "#/components/schemas/ResetPostMortemFollowUpsRequest" }, "example": { - "start_time": 1711900800, - "end_time": 1712000000, - "progress": "Triggered,Processing", - "incident_severity": "Critical,Warning", - "channel_ids": [ - 2551105804131 - ], - "limit": 20, - "p": 1 + "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", + "follow_ups": "- Add database saturation alert\n- Review cache TTL rollout" } } } } } }, - "/incident/list-by-ids": { - "post": { - "operationId": "incidentListByIds", - "summary": "List incidents by IDs", - "description": "Retrieve multiple incidents by their IDs in a single request.", + "/incident/post-mortem/info": { + "get": { + "operationId": "incidentPostMortemInfo", + "summary": "Get post-mortem", + "description": "Get the full content and auto-aggregated basics of a post-mortem report by its ID.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** (`on-call`) |\n\n## Usage\n\n- IDs that do not match an incident are omitted; `total` is the number of incidents found and `has_next_page` is always `false`.\n- Results are sorted by `start_time`, newest first.\n- This endpoint does not fill `integration_type` or `assigned_to.escalate_rule_name`.", - "href": "/en/api-reference/on-call/incidents/incident-list-by-ids", + "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- Get `post_mortem_id` from `POST /incident/post-mortem/list`, or from an incident's `post_mortem_id`.\n- Private post-mortems can be read only by account owners, admins, and members of the post-mortem's team; others get `AccessDenied`.\n- An unknown `post_mortem_id` returns `ResourceNotFound`.", + "href": "/en/api-reference/on-call/incidents/incident-post-mortem-info", "metadata": { - "sidebarTitle": "List incidents by IDs" + "sidebarTitle": "Get post-mortem" } }, "responses": { @@ -43228,7 +45586,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/IncidentListResponse" + "$ref": "#/components/schemas/PostMortemItem" } } } @@ -43237,75 +45595,46 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 1, - "has_next_page": false, - "items": [ - { - "incident_id": "69da451ef77b1b51f40e83ee", - "account_id": 2451002751131, - "channel_id": 2551105804131, - "team_id": 2477033058131, - "integration_id": 2490562293131, - "integration_ids": [ - 2490562293131 - ], - "integration_types": [ - "monit.alert" - ], - "dedup_key": "100128:prom-203.0.113.107:A:1579244238440766834:anydata", - "equals_md5": "", - "start_time": 1775912219, - "end_time": 0, - "last_time": 1775969819, - "ack_time": 0, - "close_time": 0, - "creator_id": 0, - "closer_id": 0, - "owner_id": 0, - "incident_status": "Critical", - "incident_severity": "Critical", - "progress": "Triggered", - "title": "CPU usage high - web-server-01", - "description": "", - "ai_summary": "", - "impact": "", - "root_cause": "", - "resolution": "", - "num": "0E83EE", - "frequency": "frequent", - "created_at": 1775912222, - "updated_at": 1775972145, - "snoozed_before": 0, - "group_method": "n", - "ever_muted": false, - "has_unfinished_work_item": false, - "labels": {}, - "fields": {}, - "assigned_to": { - "escalate_rule_id": "000000000000000000000000", - "layer_idx": 0, - "type": "", - "assigned_at": 0, - "id": "", - "escalate_rule_name": "" - }, - "alert_cnt": 1, - "active_alert_cnt": 1, - "alert_event_cnt": 17, - "responders": [], - "account_name": "", - "account_locale": "", - "account_time_zone": "", - "channel_name": "Ops Channel", - "channel_status": "enabled", - "detail_url": "https://app.flashcat.cloud/incident/detail/69da451ef77b1b51f40e83ee", - "silence_url": "https://app.flashcat.cloud/channel/detail/2551105804131?tab=alertSuppression&fromIncidentId=69da451ef77b1b51f40e83ee", - "integration_type": "monit.alert", - "post_mortem_id": "", - "images": null, - "manual_overrides": null - } - ] + "meta": { + "account_id": 2451002751131, + "title": "Postmortem1", + "status": "published", + "post_mortem_id": "8104935102bf89dc01ac638a5261fe7e", + "template_id": "post_mortem_default_tmpl_en-us", + "incident_ids": [ + "69bb9233331067560c718ecd" + ], + "media_count": 0, + "author_ids": [ + 2477273692131 + ], + "team_id": 2477033058131, + "channel_id": 3047621227131, + "is_private": false, + "generation": 0, + "revision": 12, + "channel_name": "Ops Channel", + "created_at_seconds": 1773900354, + "updated_at_seconds": 1773909012 + }, + "basics": { + "incidents_highest_severity": "Warning", + "incidents_earliest_start_seconds": 1761133512, + "incidents_latest_close_seconds": 1761133632, + "incidents_total_duration_seconds": 120, + "responders": [ + { + "person_id": 3790925372131, + "assigned_at": 1761133515, + "acknowledged_at": 0 + } + ] + }, + "content": { + "content": "{\"type\":\"doc\",\"content\":[]}" + }, + "follow_ups": "", + "has_active_incident": false } } } @@ -43327,37 +45656,32 @@ "$ref": "#/components/responses/ServerError" } }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListIncidentsByIdsRequest" - }, - "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee", - "69da451ef77b1b51f40e83ef" - ] - } - } + "parameters": [ + { + "name": "post_mortem_id", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "Post-mortem ID: a 32-character hex string derived from the account ID and the linked incident IDs." } - } + ] } }, - "/incident/merge": { + "/incident/post-mortem/init": { "post": { - "operationId": "incidentMerge", - "summary": "Merge incidents", - "description": "Merge one or more incidents into a target incident.", + "operationId": "postmortem-write-init", + "summary": "Initialize post-mortem", + "description": "Create a post-mortem draft from one or more incidents and a template.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- All alerts of the source incidents move to the target incident, and the target gains the sources' integrations.\n- Source incidents that are still open are closed. With `remove_source_incidents: true` they are then permanently deleted; otherwise they stay closed with an `i_merge` timeline entry that points to the target.\n- The target's progress, responders, and assignment do not change; `title`, when set, replaces the target's title.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", - "href": "/en/api-reference/on-call/incidents/incident-merge", + "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- Requires the On-call Pro license.\n- The report ID is derived from the account and the sorted `incident_ids`; calling again with the same incidents returns the existing report unchanged.\n- Fails with `InvalidParameter` when any incident is already linked to a different post-mortem.\n- Team, channel and privacy are copied from the channel of the first incident loaded; an incident without a channel cannot start a report.\n- The title is the incident titles joined by `, ` (at most 512 characters), or the template name when all titles are empty.\n- A new report starts as `drafting` with an empty body; its basics (severity, times, responders) are computed from the incidents.\n- Converted follow-ups of these incidents that are not yet bound to a report are bound to it.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/postmortem-write-init", "metadata": { - "sidebarTitle": "Merge incidents" + "sidebarTitle": "Initialize post-mortem" } }, "responses": { @@ -43374,7 +45698,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/PostMortemItem" } } } @@ -43382,7 +45706,48 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "meta": { + "account_id": 2451002751131, + "title": "Database connection timeout on prod-db-01", + "status": "drafting", + "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", + "template_id": "post_mortem_default_tmpl_en-us", + "incident_ids": [ + "69bb9233331067560c718ecd" + ], + "media_count": 0, + "author_ids": [ + 3790925372131 + ], + "team_id": 2477033058131, + "channel_id": 2551105804131, + "is_private": false, + "generation": 0, + "revision": 0, + "channel_name": "Ops Channel", + "created_at_seconds": 1773900354, + "updated_at_seconds": 1773900354 + }, + "basics": { + "incidents_highest_severity": "Critical", + "incidents_earliest_start_seconds": 1773890000, + "incidents_latest_close_seconds": 1773897200, + "incidents_total_duration_seconds": 7200, + "responders": [ + { + "person_id": 3790925372131, + "assigned_at": 1773890012, + "acknowledged_at": 1773890100 + } + ] + }, + "content": { + "content": "" + }, + "follow_ups": "", + "has_active_incident": false + } } } } @@ -43408,34 +45773,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MergeIncidentsRequest" + "$ref": "#/components/schemas/InitPostMortemRequest" }, "example": { - "source_incident_ids": [ - "69da451ef77b1b51f40e83ef", - "69da451ef77b1b51f40e83f0" + "incident_ids": [ + "69bb9233331067560c718ecd" ], - "target_incident_id": "69da451ef77b1b51f40e83ee", - "comment": "Merging related database connectivity incidents into one." + "template_id": "post_mortem_default_tmpl_en-us" } } } } } }, - "/incident/past/list": { + "/incident/post-mortem/list": { "post": { - "operationId": "incidentPastList", - "summary": "List past incidents", - "description": "List closed incidents in the same channel that resemble a given incident, to reuse past root causes and resolutions.", + "operationId": "incidentPostMortemList", + "summary": "List post-mortems", + "description": "List post-mortem reports, optionally filtered by status, team, channel, and creation time.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **5 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Professional edition or higher; otherwise the call fails with `NoLicense`.\n- Candidates are closed incidents in the same channel that started within the 30 days before the reference incident started and whose semantic similarity exceeds the channel's similarity threshold.\n- Results list incidents with longer `root_cause` plus `resolution` text first, then higher `score`, then more recent `start_time`.\n- `limit` defaults to 5 when omitted or `0`.\n- An empty `items` array means no similar incident was found, or the reference incident has not been indexed for similarity search yet.\n- The reference incident must belong to a channel; otherwise the call fails with `InvalidParameter`.", - "href": "/en/api-reference/on-call/incidents/incident-past-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- Account owners and admins see all post-mortems; other members see public ones plus private ones that belong to their own teams.\n- Results are sorted by `order_by` (default `created_at_seconds`), descending unless `asc` is `true`.\n- Items carry metadata only; fetch the full report with `GET /incident/post-mortem/info`.", + "href": "/en/api-reference/on-call/incidents/incident-post-mortem-list", "metadata": { - "sidebarTitle": "List past incidents" + "sidebarTitle": "List post-mortems" } }, "responses": { @@ -43452,7 +45815,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListPastIncidentsResponse" + "$ref": "#/components/schemas/ListPostMortemsResponse" } } } @@ -43461,7 +45824,32 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [] + "total": 3, + "has_next_page": false, + "items": [ + { + "account_id": 2451002751131, + "title": "Postmortem1", + "status": "published", + "post_mortem_id": "8104935102bf89dc01ac638a5261fe7e", + "template_id": "post_mortem_default_tmpl_en-us", + "incident_ids": [ + "69bb9233331067560c718ecd" + ], + "media_count": 0, + "author_ids": [ + 2477273692131 + ], + "team_id": 2477033058131, + "channel_id": 3047621227131, + "is_private": false, + "generation": 0, + "revision": 12, + "channel_name": "Ops Channel", + "created_at_seconds": 1773900354, + "updated_at_seconds": 1773909012 + } + ] } } } @@ -43488,30 +45876,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListPastIncidentsRequest" + "$ref": "#/components/schemas/ListPostMortemsRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee", - "limit": 5 + "status": "published", + "p": 1, + "limit": 20 } } } } } }, - "/incident/post-mortem/basics/reset": { + "/incident/post-mortem/status/reset": { "post": { - "operationId": "postmortem-write-reset-basics", - "summary": "Update post-mortem basics", - "description": "Overwrite the incident facts (severity, times, responders) stored on a post-mortem report.", + "operationId": "postmortem-write-reset-status", + "summary": "Update post-mortem status", + "description": "Set a post-mortem report to drafting or published.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- Full overwrite: omitted `incidents_latest_close_seconds` and `incidents_total_duration_seconds` become 0, and omitted `responder_ids` clears the responders.\n- IDs in `responder_ids` that do not resolve to a person are dropped; each stored responder gets the current time as `assigned_at` and `acknowledged_at` = 0.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-basics", + "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- Status can move both ways. Only a `drafting` report accepts `POST /incident/post-mortem/content/reset`.\n- Publishing deletes uploaded media files that the report body no longer references.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-status", "metadata": { - "sidebarTitle": "Update post-mortem basics" + "sidebarTitle": "Update post-mortem status" } }, "responses": { @@ -43561,36 +45950,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResetPostMortemBasicsRequest" + "$ref": "#/components/schemas/ResetPostMortemStatusRequest" }, "example": { "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", - "incidents_highest_severity": "Critical", - "incidents_earliest_start_seconds": 1773890000, - "incidents_latest_close_seconds": 1773897200, - "incidents_total_duration_seconds": 7200, - "responder_ids": [ - 3790925372131 - ] + "status": "published" } } } } } }, - "/incident/post-mortem/content/reset": { + "/incident/post-mortem/template/delete": { "post": { - "operationId": "incident-post-mortem-write-reset-content", - "summary": "Reset post-mortem content", - "description": "Replace the body of a drafting post-mortem report with Markdown.", + "operationId": "postmortem-write-delete-template", + "summary": "Delete post-mortem template", + "description": "Delete a custom post-mortem template.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- The report must be drafting and its current revision must equal `expected_revision`; otherwise the API returns `409 Conflict`.\n- Reuse an `idempotency_key` only for the same report, revision, and Markdown content; different reuse returns `409 Conflict`.\n- While another reset of the same report is still running, the call returns `RequestTooFrequently`; retry later.\n- A successful reset disconnects the previous collaboration (Yjs) room. Reconnect to the new generation room `post-mortem-{accountId}-{postMortemId}-g{N}` (generation 0 has no `-g` suffix). The reset cannot be rolled back.\n- Markdown content is limited to 4 MiB.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-post-mortem-write-reset-content", + "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- Requires the On-call Pro license.\n- Built-in templates (`post_mortem_default_tmpl_*`) cannot be deleted; an unknown ID returns `ResourceNotFound`.\n- Requires being an account owner or admin, or a member of the template's team.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/postmortem-write-delete-template", "metadata": { - "sidebarTitle": "Reset post-mortem content" + "sidebarTitle": "Delete post-mortem template" } }, "responses": { @@ -43607,23 +45990,14 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PostMortemContentResetResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", - "generation": 2, - "revision": 12, - "previous_generation": 1, - "previous_revision": 11, - "markdown_bytes": 88, - "markdown_sha256": "70d764e77e68f8fbfa14d72a235ac07b0110768b8380c8e3436459ebaf02a7c0" - } + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } } @@ -43637,105 +46011,122 @@ "403": { "$ref": "#/components/responses/Forbidden" }, - "409": { - "description": "The report is not drafting, the revision is stale, or the idempotency key was reused for a different request.", + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeletePostMortemTemplateRequest" + }, + "example": { + "template_id": "kQ3vXn8pR2mT7wYbZc4dEf" + } + } + } + } + } + }, + "/incident/post-mortem/template/info": { + "get": { + "operationId": "postmortem-read-template-info", + "summary": "Get post-mortem template detail", + "description": "Return one post-mortem template by ID.", + "tags": [ + "On-call/Incidents" + ], + "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- Requires the On-call Pro license.\n- Accepts the built-in IDs `post_mortem_default_tmpl_zh-cn` and `post_mortem_default_tmpl_en-us` regardless of request language; an unknown ID returns `ResourceNotFound`.", + "href": "/en/api-reference/on-call/incidents/postmortem-read-template-info", + "metadata": { + "sidebarTitle": "Get post-mortem template detail" + } + }, + "responses": { + "200": { + "description": "Success", "content": { "application/json": { "schema": { - "type": "object", - "required": [ - "request_id", - "error" - ], - "properties": { - "request_id": { - "type": "string" + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" }, - "error": { + { "type": "object", - "required": [ - "code", - "message" - ], "properties": { - "code": { - "type": "string", - "enum": [ - "Conflict" - ] - }, - "message": { - "type": "string" + "data": { + "$ref": "#/components/schemas/PostMortemTemplate" } } } - } + ] }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "error": { - "code": "Conflict", - "message": "expected_revision conflict: request has 11 but current revision is 12" + "data": { + "account_id": 0, + "template_id": "post_mortem_default_tmpl_en-us", + "name": "Default Post Mortem Report Template", + "description": "Standard post-mortem template with common sections", + "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", + "content_markdown": "## Summary\n> Provide a high-level description of the incident.", + "team_id": 0, + "created_at_seconds": 0, + "updated_at_seconds": 0 } } } } }, - "413": { - "description": "Markdown content exceeds the 4 MiB limit.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "error": { - "code": "EntityTooLarge", - "message": "markdown exceeds maximum size" - } - } - } - } + "400": { + "$ref": "#/components/responses/BadRequest" }, - "429": { - "$ref": "#/components/responses/TooManyRequests" + "401": { + "$ref": "#/components/responses/Unauthorized" }, - "500": { - "$ref": "#/components/responses/ServerError" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResetPostMortemContentRequest" - }, - "example": { - "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", - "markdown": "# Database saturation incident\n\nThe database pool was exhausted; added saturation alert.", - "expected_revision": 11, - "idempotency_key": "postmortem-reset-d3c9a7f2-11" - } - } + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" } - } + }, + "parameters": [ + { + "name": "template_id", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "Template ID: a built-in ID such as `post_mortem_default_tmpl_en-us`, or a custom template ID from `POST /incident/post-mortem/template/list`." + } + ] } }, - "/incident/post-mortem/delete": { + "/incident/post-mortem/template/list": { "post": { - "operationId": "incidentPostMortemDelete", - "summary": "Delete post-mortem", - "description": "Permanently delete a post-mortem report together with its uploaded media.", + "operationId": "postmortem-read-list-templates", + "summary": "List post-mortem templates", + "description": "Return the built-in post-mortem template followed by the account's custom templates.", "tags": [ "On-call/Incidents" ], "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- Requires the Professional edition or higher; otherwise the call fails with `NoLicense`.\n- The caller must be an account owner or admin, or a member of the post-mortem's team; otherwise the call fails with `AccessDenied`.\n- Linked incidents are unlinked, so their `post_mortem_id` becomes empty.\n- An unknown `post_mortem_id` returns `ResourceNotFound`.\n- On success the response has no `data` field.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-post-mortem-delete", + "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- Requires the On-call Pro license.\n- The built-in template always comes first and matches the request language: Chinese returns `post_mortem_default_tmpl_zh-cn`, anything else `post_mortem_default_tmpl_en-us`. `total` includes it.\n- Custom templates are sorted by `created_at_seconds`, newest first unless `asc` is true.\n- Paginate with `p` and `limit`; `p` × `limit` must not exceed 10,000.\n- Built-in templates have `account_id`, `team_id` and both timestamps set to 0.", + "href": "/en/api-reference/on-call/incidents/postmortem-read-list-templates", "metadata": { - "sidebarTitle": "Delete post-mortem" + "sidebarTitle": "List post-mortem templates" } }, "responses": { @@ -43752,14 +46143,42 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListPostMortemTemplatesResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 2, + "has_next_page": false, + "items": [ + { + "account_id": 0, + "template_id": "post_mortem_default_tmpl_en-us", + "name": "Default Post Mortem Report Template", + "description": "Standard post-mortem template with common sections", + "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", + "content_markdown": "## Summary\n> Provide a high-level description of the incident.", + "team_id": 0, + "created_at_seconds": 0, + "updated_at_seconds": 0 + }, + { + "account_id": 2451002751131, + "template_id": "kQ3vXn8pR2mT7wYbZc4dEf", + "name": "Production incident template", + "description": "Template for production incident reviews.", + "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", + "content_markdown": "## Summary\nDescribe what happened.", + "team_id": 2477033058131, + "created_at_seconds": 1773900000, + "updated_at_seconds": 1773903600 + } + ] + } } } } @@ -43785,29 +46204,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeletePostMortemRequest" + "$ref": "#/components/schemas/ListPostMortemTemplatesRequest" }, "example": { - "post_mortem_id": "8104935102bf89dc01ac638a5261fe7e" + "p": 1, + "limit": 20, + "order_by": "created_at_seconds", + "asc": false } } } } } }, - "/incident/post-mortem/follow-ups/reset": { + "/incident/post-mortem/template/upsert": { "post": { - "operationId": "postmortem-write-reset-follow-ups", - "summary": "Update post-mortem follow-ups", - "description": "Replace the free-text follow-ups string stored on a post-mortem report.", + "operationId": "postmortem-write-upsert-template", + "summary": "Create or update post-mortem template", + "description": "Create a custom post-mortem template, or replace an existing one identified by `template_id`.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- Works in any report status. Omitting `follow_ups` or sending `\"\"` clears the string.\n- When `follow_ups` is a JSON array in the console's follow-up format, its entries are also synced into structured follow-up work items (`source_kind` = `legacy_follow_up`); other text leaves the structured items unchanged.\n- To manage individual follow-ups, prefer the `/incident/work-item/*` endpoints.\n- The caller is added to the report's `author_ids`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-follow-ups", + "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- Requires the On-call Pro license.\n- Omit `template_id` to create: `team_id` must name an existing team, and the server generates the template ID.\n- With `template_id`, the existing custom template is replaced; an unknown ID returns `ResourceNotFound`. Updating requires being an account owner or admin, or a member of the template's team.\n- All text fields are replaced: an omitted `description` or `content_markdown` becomes empty. On update, `team_id` moves the template to that team; omit it or send 0 to keep the current team.\n- Built-in templates (`post_mortem_default_tmpl_*`) cannot be modified.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/postmortem-write-upsert-template", "metadata": { - "sidebarTitle": "Update post-mortem follow-ups" + "sidebarTitle": "Create or update post-mortem template" } }, "responses": { @@ -43824,14 +46246,25 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/PostMortemTemplate" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "account_id": 2451002751131, + "template_id": "kQ3vXn8pR2mT7wYbZc4dEf", + "name": "Production incident template", + "description": "Template for production incident reviews.", + "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", + "content_markdown": "## Summary\nDescribe what happened.", + "team_id": 2477033058131, + "created_at_seconds": 1773900000, + "updated_at_seconds": 1773903600 + } } } } @@ -43857,30 +46290,33 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResetPostMortemFollowUpsRequest" + "$ref": "#/components/schemas/UpsertPostMortemTemplateRequest" }, "example": { - "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", - "follow_ups": "- Add database saturation alert\n- Review cache TTL rollout" + "team_id": 2477033058131, + "name": "Production incident template", + "description": "Template for production incident reviews.", + "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", + "content_markdown": "## Summary\nDescribe what happened." } } } } } }, - "/incident/post-mortem/info": { - "get": { - "operationId": "incidentPostMortemInfo", - "summary": "Get post-mortem", - "description": "Get the full content and auto-aggregated basics of a post-mortem report by its ID.", + "/incident/post-mortem/title/reset": { + "post": { + "operationId": "postmortem-write-reset-title", + "summary": "Update post-mortem title", + "description": "Replace the title of a post-mortem report.", "tags": [ "On-call/Incidents" ], "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- Get `post_mortem_id` from `POST /incident/post-mortem/list`, or from an incident's `post_mortem_id`.\n- Private post-mortems can be read only by account owners, admins, and members of the post-mortem's team; others get `AccessDenied`.\n- An unknown `post_mortem_id` returns `ResourceNotFound`.", - "href": "/en/api-reference/on-call/incidents/incident-post-mortem-info", + "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- The caller is added to the report's `author_ids`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-title", "metadata": { - "sidebarTitle": "Get post-mortem" + "sidebarTitle": "Update post-mortem title" } }, "responses": { @@ -43897,56 +46333,14 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PostMortemItem" + "$ref": "#/components/schemas/EmptyResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "meta": { - "account_id": 2451002751131, - "title": "Postmortem1", - "status": "published", - "post_mortem_id": "8104935102bf89dc01ac638a5261fe7e", - "template_id": "post_mortem_default_tmpl_en-us", - "incident_ids": [ - "69bb9233331067560c718ecd" - ], - "media_count": 0, - "author_ids": [ - 2477273692131 - ], - "team_id": 2477033058131, - "channel_id": 3047621227131, - "is_private": false, - "generation": 0, - "revision": 12, - "channel_name": "Ops Channel", - "created_at_seconds": 1773900354, - "updated_at_seconds": 1773909012 - }, - "basics": { - "incidents_highest_severity": "Warning", - "incidents_earliest_start_seconds": 1761133512, - "incidents_latest_close_seconds": 1761133632, - "incidents_total_duration_seconds": 120, - "responders": [ - { - "person_id": 3790925372131, - "assigned_at": 1761133515, - "acknowledged_at": 0 - } - ] - }, - "content": { - "content": "{\"type\":\"doc\",\"content\":[]}" - }, - "follow_ups": "", - "has_active_incident": false - } + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } } @@ -43967,32 +46361,35 @@ "$ref": "#/components/responses/ServerError" } }, - "parameters": [ - { - "name": "post_mortem_id", - "in": "query", - "required": true, - "schema": { - "type": "string" - }, - "description": "Post-mortem ID: a 32-character hex string derived from the account ID and the linked incident IDs." + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResetPostMortemTitleRequest" + }, + "example": { + "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", + "title": "Production API latency incident" + } + } } - ] + } } }, - "/incident/post-mortem/init": { + "/incident/remove": { "post": { - "operationId": "postmortem-write-init", - "summary": "Initialize post-mortem", - "description": "Create a post-mortem draft from one or more incidents and a template.", + "operationId": "incidentRemove", + "summary": "Delete an incident", + "description": "Permanently delete incidents together with their alerts, raw events, and timelines.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- The report ID is derived from the account and the sorted `incident_ids`; calling again with the same incidents returns the existing report unchanged.\n- Fails with `InvalidParameter` when any incident is already linked to a different post-mortem.\n- Team, channel and privacy are copied from the channel of the first incident loaded; an incident without a channel cannot start a report.\n- The title is the incident titles joined by `, ` (at most 512 characters), or the template name when all titles are empty.\n- A new report starts as `drafting` with an empty body; its basics (severity, times, responders) are computed from the incidents.\n- Converted follow-ups of these incidents that are not yet bound to a report are bound to it.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/postmortem-write-init", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Deletion cannot be undone. Analytics statistics of the deleted incidents are removed in the background.\n- Fails with `InvalidParameter` if any incident belongs to a channel the caller cannot access.\n- IDs that do not match an incident are ignored.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", + "href": "/en/api-reference/on-call/incidents/incident-remove", "metadata": { - "sidebarTitle": "Initialize post-mortem" + "sidebarTitle": "Delete an incident" } }, "responses": { @@ -44009,7 +46406,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PostMortemItem" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -44017,48 +46414,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "meta": { - "account_id": 2451002751131, - "title": "Database connection timeout on prod-db-01", - "status": "drafting", - "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", - "template_id": "post_mortem_default_tmpl_en-us", - "incident_ids": [ - "69bb9233331067560c718ecd" - ], - "media_count": 0, - "author_ids": [ - 3790925372131 - ], - "team_id": 2477033058131, - "channel_id": 2551105804131, - "is_private": false, - "generation": 0, - "revision": 0, - "channel_name": "Ops Channel", - "created_at_seconds": 1773900354, - "updated_at_seconds": 1773900354 - }, - "basics": { - "incidents_highest_severity": "Critical", - "incidents_earliest_start_seconds": 1773890000, - "incidents_latest_close_seconds": 1773897200, - "incidents_total_duration_seconds": 7200, - "responders": [ - { - "person_id": 3790925372131, - "assigned_at": 1773890012, - "acknowledged_at": 1773890100 - } - ] - }, - "content": { - "content": "" - }, - "follow_ups": "", - "has_active_incident": false - } + "data": {} } } } @@ -44084,32 +46440,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InitPostMortemRequest" + "$ref": "#/components/schemas/RemoveIncidentRequest" }, "example": { "incident_ids": [ - "69bb9233331067560c718ecd" - ], - "template_id": "post_mortem_default_tmpl_en-us" + "69da451ef77b1b51f40e83ee" + ] } } } } } }, - "/incident/post-mortem/list": { + "/incident/reopen": { "post": { - "operationId": "incidentPostMortemList", - "summary": "List post-mortems", - "description": "List post-mortem reports, optionally filtered by status, team, channel, and creation time.", + "operationId": "incidentReopen", + "summary": "Reopen incident", + "description": "Reopen closed incidents and dispatch them again from the first escalation level.", "tags": [ "On-call/Incidents" ], "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- Account owners and admins see all post-mortems; other members see public ones plus private ones that belong to their own teams.\n- Results are sorted by `order_by` (default `created_at_seconds`), descending unless `asc` is `true`.\n- Items carry metadata only; fetch the full report with `GET /incident/post-mortem/info`.", - "href": "/en/api-reference/on-call/incidents/incident-post-mortem-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Every incident must be `Closed`; otherwise the whole call fails with `InvalidParameter`.\n- Reopened incidents return to `Triggered`, with `ack_time`, `close_time`, `closer_id`, and every responder's acknowledgement reset.\n- Each incident is reassigned to its previous assignment target starting at the first escalation level, with `assigned_to.type` set to `reopen`.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", + "href": "/en/api-reference/on-call/incidents/incident-reopen", "metadata": { - "sidebarTitle": "List post-mortems" + "sidebarTitle": "Reopen incident" } }, "responses": { @@ -44126,7 +46481,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListPostMortemsResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -44134,34 +46489,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "total": 3, - "has_next_page": false, - "items": [ - { - "account_id": 2451002751131, - "title": "Postmortem1", - "status": "published", - "post_mortem_id": "8104935102bf89dc01ac638a5261fe7e", - "template_id": "post_mortem_default_tmpl_en-us", - "incident_ids": [ - "69bb9233331067560c718ecd" - ], - "media_count": 0, - "author_ids": [ - 2477273692131 - ], - "team_id": 2477033058131, - "channel_id": 3047621227131, - "is_private": false, - "generation": 0, - "revision": 12, - "channel_name": "Ops Channel", - "created_at_seconds": 1773900354, - "updated_at_seconds": 1773909012 - } - ] - } + "data": {} } } } @@ -44187,31 +46515,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListPostMortemsRequest" + "$ref": "#/components/schemas/ReopenIncidentRequest" }, "example": { - "status": "published", - "p": 1, - "limit": 20 + "incident_ids": [ + "69da451ef77b1b51f40e83ee" + ], + "reason": "Monitoring detected the issue recurred after the initial fix." } } } } } }, - "/incident/post-mortem/status/reset": { + "/incident/reset": { "post": { - "operationId": "postmortem-write-reset-status", - "summary": "Update post-mortem status", - "description": "Set a post-mortem report to drafting or published.", + "operationId": "incidentReset", + "summary": "Update incident fields", + "description": "Update an incident's title, description, impact, root cause, resolution, or severity in one call.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- Status can move both ways. Only a `drafting` report accepts `POST /incident/post-mortem/content/reset`.\n- Publishing deletes uploaded media files that the report body no longer references.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-status", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- At least one field must be provided. Omitted fields and empty strings keep their current values, so this endpoint cannot clear a field.\n- Values equal to the current ones are skipped. Each changed field adds its own timeline entry (`i_r_title`, `i_r_desc`, `i_r_impact`, `i_r_rc`, `i_r_rsltn`, or `i_r_severity`).\n- Changing `title`, `description`, or `incident_severity` adds that field to `manual_overrides`; after that, alerts merged into the incident no longer overwrite it.\n- Closed incidents can be updated as well.", + "href": "/en/api-reference/on-call/incidents/incident-reset", "metadata": { - "sidebarTitle": "Update post-mortem status" + "sidebarTitle": "Update incident fields" } }, "responses": { @@ -44235,7 +46564,8 @@ ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } } @@ -44261,30 +46591,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResetPostMortemStatusRequest" + "$ref": "#/components/schemas/UpdateIncidentFieldsRequest" }, "example": { - "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", - "status": "published" + "incident_id": "69da451ef77b1b51f40e83ee", + "title": "Database connection timeout - prod-db-01 primary", + "incident_severity": "Critical" } } } } } }, - "/incident/post-mortem/template/delete": { + "/incident/resolve": { "post": { - "operationId": "postmortem-write-delete-template", - "summary": "Delete post-mortem template", - "description": "Delete a custom post-mortem template.", + "operationId": "incidentResolve", + "summary": "Resolve incident", + "description": "Close one or more incidents, optionally recording root cause, resolution, and resolution form values.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- Built-in templates (`post_mortem_default_tmpl_*`) cannot be deleted; an unknown ID returns `ResourceNotFound`.\n- Requires being an account owner or admin, or a member of the template's team.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/postmortem-write-delete-template", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- When a resolution form applies, `custom_fields`, `summary`, and `images` must match its visible elements and required rules.\n- For a batch, form values are accepted only when every selected incident resolves to the same form; otherwise resolve incidents individually.\n- The legacy `values` and `custom_values` properties are rejected; use `custom_fields`.\n- Incidents that are already closed are skipped without error; an unknown ID fails the whole call with `InvalidParameter`.\n- Resolving a `Triggered` incident first acknowledges it on behalf of the caller.\n- After closing, unfinished action items of the incident are converted to follow-ups, and later events no longer merge into the incident's existing alerts.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", + "href": "/en/api-reference/on-call/incidents/incident-resolve", "metadata": { - "sidebarTitle": "Delete post-mortem template" + "sidebarTitle": "Resolve incident" } }, "responses": { @@ -44308,7 +46639,8 @@ ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } } @@ -44334,29 +46666,33 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeletePostMortemTemplateRequest" + "$ref": "#/components/schemas/ResolveIncidentRequest" }, "example": { - "template_id": "kQ3vXn8pR2mT7wYbZc4dEf" + "incident_ids": [ + "69da451ef77b1b51f40e83ee" + ], + "root_cause": "Memory leak in the connection pool caused by a missing cleanup call.", + "resolution": "Deployed hotfix v2.3.1 and restarted the affected service." } } } } } }, - "/incident/post-mortem/template/info": { - "get": { - "operationId": "postmortem-read-template-info", - "summary": "Get post-mortem template detail", - "description": "Return one post-mortem template by ID.", + "/incident/responder/add": { + "post": { + "operationId": "incidentResponderAdd", + "summary": "Add incident responder", + "description": "Add members as responders to an open incident and notify them.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- Accepts the built-in IDs `post_mortem_default_tmpl_zh-cn` and `post_mortem_default_tmpl_en-us` regardless of request language; an unknown ID returns `ResourceNotFound`.", - "href": "/en/api-reference/on-call/incidents/postmortem-read-template-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Existing responders are kept, and IDs that are already responders are skipped. To replace the responder set, use `POST /incident/assign`.\n- Closed incidents are rejected with `InvalidParameter`.\n- Member IDs that do not exist in the account are ignored.\n- New responders are notified according to `notify`; by default each follows their personal notification preference.", + "href": "/en/api-reference/on-call/incidents/incident-responder-add", "metadata": { - "sidebarTitle": "Get post-mortem template detail" + "sidebarTitle": "Add incident responder" } }, "responses": { @@ -44373,7 +46709,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PostMortemTemplate" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -44381,17 +46717,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "account_id": 0, - "template_id": "post_mortem_default_tmpl_en-us", - "name": "Default Post Mortem Report Template", - "description": "Standard post-mortem template with common sections", - "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", - "content_markdown": "## Summary\n> Provide a high-level description of the incident.", - "team_id": 0, - "created_at_seconds": 0, - "updated_at_seconds": 0 - } + "data": {} } } } @@ -44412,32 +46738,38 @@ "$ref": "#/components/responses/ServerError" } }, - "parameters": [ - { - "name": "template_id", - "in": "query", - "required": true, - "schema": { - "type": "string" - }, - "description": "Template ID: a built-in ID such as `post_mortem_default_tmpl_en-us`, or a custom template ID from `POST /incident/post-mortem/template/list`." + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddIncidentResponderRequest" + }, + "example": { + "incident_id": "69da451ef77b1b51f40e83ee", + "person_ids": [ + 2476444212131, + 2476444212132 + ] + } + } } - ] + } } }, - "/incident/post-mortem/template/list": { + "/incident/sdp/request/list": { "post": { - "operationId": "postmortem-read-list-templates", - "summary": "List post-mortem templates", - "description": "Return the built-in post-mortem template followed by the account's custom templates.", + "operationId": "incident-service-desk-plus-request-read-list", + "summary": "Get ServiceDeskPlus linked incidents", + "description": "List synchronization mappings between ServiceDeskPlus requests and Flashduty incidents.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- The built-in template always comes first and matches the request language: Chinese returns `post_mortem_default_tmpl_zh-cn`, anything else `post_mortem_default_tmpl_en-us`. `total` includes it.\n- Custom templates are sorted by `created_at_seconds`, newest first unless `asc` is true.\n- Paginate with `p` and `limit`; `p` × `limit` must not exceed 10,000.\n- Built-in templates have `account_id`, `team_id` and both timestamps set to 0.", - "href": "/en/api-reference/on-call/incidents/postmortem-read-list-templates", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Use this endpoint to inspect synchronization mappings between ServiceDeskPlus requests and Flashduty incidents, including the external request link and sync status.\n- When `incident_id` is not provided, `start_time` and `end_time` are required Unix-second timestamps; the time window cannot exceed 30 days.\n- `status` accepts only `success` and `failed`, representing successful and failed synchronization records.\n- Results are sorted by the internal record ID. Set `asc` to `true` for ascending order; otherwise records are returned descending.\n- Pagination uses only `search_after_ctx`: pass the value returned by the previous response; `p` is ignored.", + "href": "/en/api-reference/on-call/incidents/incident-service-desk-plus-request-read-list", "metadata": { - "sidebarTitle": "List post-mortem templates" + "sidebarTitle": "Get ServiceDeskPlus linked incidents" } }, "responses": { @@ -44454,7 +46786,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListPostMortemTemplatesResponse" + "$ref": "#/components/schemas/ServiceDeskPlusRequestListResponse" } } } @@ -44463,32 +46795,22 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 2, - "has_next_page": false, "items": [ { - "account_id": 0, - "template_id": "post_mortem_default_tmpl_en-us", - "name": "Default Post Mortem Report Template", - "description": "Standard post-mortem template with common sections", - "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", - "content_markdown": "## Summary\n> Provide a high-level description of the incident.", - "team_id": 0, - "created_at_seconds": 0, - "updated_at_seconds": 0 - }, - { - "account_id": 2451002751131, - "template_id": "kQ3vXn8pR2mT7wYbZc4dEf", - "name": "Production incident template", - "description": "Template for production incident reviews.", - "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", - "content_markdown": "## Summary\nDescribe what happened.", - "team_id": 2477033058131, - "created_at_seconds": 1773900000, - "updated_at_seconds": 1773903600 + "created_at": 1779514631, + "status": "success", + "request_id": "100000000001", + "request_link": "https://servicedesk.example.com/app/itdesk/ui/requests/100000000001/details", + "integration_id": 98765, + "incident_id": "685d7f4e51b9a9a6d4d0c123", + "incident_title": "Checkout API 5xx rate increased", + "channel_id": 12345, + "channel_name": "Payments" } - ] + ], + "total": 1, + "has_next_page": false, + "search_after_ctx": "" } } } @@ -44515,32 +46837,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListPostMortemTemplatesRequest" + "$ref": "#/components/schemas/ServiceDeskPlusRequestListRequest" }, "example": { - "p": 1, - "limit": 20, - "order_by": "created_at_seconds", - "asc": false + "start_time": 1779513600, + "end_time": 1779600000, + "status": "success", + "channel_ids": [ + 12345 + ], + "limit": 20 } } } } } }, - "/incident/post-mortem/template/upsert": { + "/incident/snooze": { "post": { - "operationId": "postmortem-write-upsert-template", - "summary": "Create or update post-mortem template", - "description": "Create a custom post-mortem template, or replace an existing one identified by `template_id`.", + "operationId": "incidentSnooze", + "summary": "Snooze incident", + "description": "Pause notifications for acknowledged incidents for a given number of minutes.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- Omit `template_id` to create: `team_id` must name an existing team, and the server generates the template ID.\n- With `template_id`, the existing custom template is replaced; an unknown ID returns `ResourceNotFound`. Updating requires being an account owner or admin, or a member of the template's team.\n- All text fields are replaced: an omitted `description` or `content_markdown` becomes empty. On update, `team_id` moves the template to that team; omit it or send 0 to keep the current team.\n- Built-in templates (`post_mortem_default_tmpl_*`) cannot be modified.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/postmortem-write-upsert-template", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only incidents in `Processing` progress can be snoozed; any other progress fails the whole call with `InvalidParameter`.\n- Notifications resume automatically after `minutes` elapse, or earlier through `POST /incident/wake`. The snooze end time is stored in the incident's `snoozed_before` (Unix seconds).\n- The snooze is also cleared when the incident is reassigned or returns to `Triggered`.", + "href": "/en/api-reference/on-call/incidents/incident-snooze", "metadata": { - "sidebarTitle": "Create or update post-mortem template" + "sidebarTitle": "Snooze incident" } }, "responses": { @@ -44557,7 +46882,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PostMortemTemplate" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -44565,17 +46890,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "account_id": 2451002751131, - "template_id": "kQ3vXn8pR2mT7wYbZc4dEf", - "name": "Production incident template", - "description": "Template for production incident reviews.", - "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", - "content_markdown": "## Summary\nDescribe what happened.", - "team_id": 2477033058131, - "created_at_seconds": 1773900000, - "updated_at_seconds": 1773903600 - } + "data": {} } } } @@ -44601,33 +46916,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpsertPostMortemTemplateRequest" + "$ref": "#/components/schemas/SnoozeIncidentRequest" }, "example": { - "team_id": 2477033058131, - "name": "Production incident template", - "description": "Template for production incident reviews.", - "content": "[{\"type\":\"heading\",\"props\":{\"level\":2},\"content\":\"Summary\"}]", - "content_markdown": "## Summary\nDescribe what happened." + "incident_ids": [ + "69da451ef77b1b51f40e83ee" + ], + "minutes": 60 } } } } } }, - "/incident/post-mortem/title/reset": { + "/incident/unack": { "post": { - "operationId": "postmortem-write-reset-title", - "summary": "Update post-mortem title", - "description": "Replace the title of a post-mortem report.", + "operationId": "incidentUnack", + "summary": "Unacknowledge incident", + "description": "Withdraw the calling member's acknowledgement of one or more incidents.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- The caller must be an account owner or admin, or a member of the report's team; otherwise the call returns `AccessDenied`.\n- The caller is added to the report's `author_ids`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/postmortem-write-reset-title", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only the calling member's acknowledgement is removed. The incident returns to `Triggered`, and any snooze is cleared, only when no other responder still has it acknowledged.\n- Every incident must be in `Processing`; a `Triggered` or `Closed` incident fails the whole call with `InvalidParameter`.", + "href": "/en/api-reference/on-call/incidents/incident-unack", "metadata": { - "sidebarTitle": "Update post-mortem title" + "sidebarTitle": "Unacknowledge incident" } }, "responses": { @@ -44651,7 +46965,8 @@ ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } } @@ -44677,30 +46992,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResetPostMortemTitleRequest" + "$ref": "#/components/schemas/UnackIncidentRequest" }, "example": { - "post_mortem_id": "d3c9a7f2e5b14c8a9f0e6b2d4a1c7e35", - "title": "Production API latency incident" + "incident_ids": [ + "69da451ef77b1b51f40e83ee" + ] } } } } } }, - "/incident/remove": { + "/incident/wake": { "post": { - "operationId": "incidentRemove", - "summary": "Delete an incident", - "description": "Permanently delete incidents together with their alerts, raw events, and timelines.", + "operationId": "incidentWake", + "summary": "Wake incident", + "description": "End the snooze on incidents so that their notifications resume immediately.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Deletion cannot be undone. Analytics statistics of the deleted incidents are removed in the background.\n- Fails with `InvalidParameter` if any incident belongs to a channel the caller cannot access.\n- IDs that do not match an incident are ignored.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", - "href": "/en/api-reference/on-call/incidents/incident-remove", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Incidents whose snooze has already ended are skipped; a closed incident fails the whole call with `InvalidParameter`.", + "href": "/en/api-reference/on-call/incidents/incident-wake", "metadata": { - "sidebarTitle": "Delete an incident" + "sidebarTitle": "Wake incident" } }, "responses": { @@ -44751,7 +47067,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RemoveIncidentRequest" + "$ref": "#/components/schemas/WakeIncidentRequest" }, "example": { "incident_ids": [ @@ -44763,19 +47079,19 @@ } } }, - "/incident/reopen": { + "/incident/war-room/add-member": { "post": { - "operationId": "incidentReopen", - "summary": "Reopen incident", - "description": "Reopen closed incidents and dispatch them again from the first escalation level.", + "operationId": "incident-write-add-war-room-member", + "summary": "Add war-room member", + "description": "Add members to an existing incident war room on Feishu (Lark), DingTalk, WeCom, or Slack.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Every incident must be `Closed`; otherwise the whole call fails with `InvalidParameter`.\n- Reopened incidents return to `Triggered`, with `ack_time`, `close_time`, `closer_id`, and every responder's acknowledgement reset.\n- Each incident is reassigned to its previous assignment target starting at the first escalation level, with `assigned_to.type` set to `reopen`.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", - "href": "/en/api-reference/on-call/incidents/incident-reopen", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the On-call Pro license.\n- `chat_id` must identify a war room created through Flashduty on integration `integration_id`; otherwise the call returns `ResourceNotFound`.\n- Only Feishu (Lark), DingTalk, WeCom and Slack integrations support war rooms; other integrations return `InvalidParameter`.\n- Every ID in `member_ids` must be a person in the account; one unknown ID fails the whole request.\n- On success `data` is the string `ok`.", + "href": "/en/api-reference/on-call/incidents/incident-write-add-war-room-member", "metadata": { - "sidebarTitle": "Reopen incident" + "sidebarTitle": "Add war-room member" } }, "responses": { @@ -44792,7 +47108,8 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "type": "string", + "description": "Returns the literal \"ok\" on success." } } } @@ -44800,7 +47117,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": "ok" } } } @@ -44826,32 +47143,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReopenIncidentRequest" + "$ref": "#/components/schemas/AddWarRoomMemberRequest" }, "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee" - ], - "reason": "Monitoring detected the issue recurred after the initial fix." + "integration_id": 2551105804131, + "chat_id": "oc_5ce6d572455d361153b7cb51da133945", + "member_ids": [ + 3790925372131, + 5068740052131 + ] } } } } } }, - "/incident/reset": { + "/incident/war-room/create": { "post": { - "operationId": "incidentReset", - "summary": "Update incident fields", - "description": "Update an incident's title, description, impact, root cause, resolution, or severity in one call.", + "operationId": "incidentWarRoomCreate", + "summary": "Create war room", + "description": "Create an IM group chat as the war room for an incident and invite members into it.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- At least one field must be provided. Omitted fields and empty strings keep their current values, so this endpoint cannot clear a field.\n- Values equal to the current ones are skipped. Each changed field adds its own timeline entry (`i_r_title`, `i_r_desc`, `i_r_impact`, `i_r_rc`, `i_r_rsltn`, or `i_r_severity`).\n- Changing `title`, `description`, or `incident_severity` adds that field to `manual_overrides`; after that, alerts merged into the incident no longer overwrite it.\n- Closed incidents can be updated as well.", - "href": "/en/api-reference/on-call/incidents/incident-reset", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Professional edition or higher; otherwise the call fails with `NoLicense`.\n- The IM integration must be enabled with war room turned on. Feishu, DingTalk, WeCom (self-built app only), and Slack are supported.\n- An incident can have only one war room. Calling again with the same `integration_id` returns the existing group (with an empty `share_link`); a different `integration_id` fails with `InvalidParameter`.\n- A concurrent creation for the same incident returns `RequestTooFrequently`.\n- A successful creation adds an `i_wr_create` timeline entry.", + "href": "/en/api-reference/on-call/incidents/incident-war-room-create", "metadata": { - "sidebarTitle": "Update incident fields" + "sidebarTitle": "Create war room" } }, "responses": { @@ -44868,7 +47187,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/WarRoom" } } } @@ -44876,7 +47195,11 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000", + "chat_name": "Incident #0E83EE war room", + "share_link": "" + } } } } @@ -44902,31 +47225,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateIncidentFieldsRequest" + "$ref": "#/components/schemas/CreateWarRoomRequest" }, "example": { "incident_id": "69da451ef77b1b51f40e83ee", - "title": "Database connection timeout - prod-db-01 primary", - "incident_severity": "Critical" + "integration_id": 2490562293131, + "add_observers": true } } } } } }, - "/incident/resolve": { + "/incident/war-room/default-observers": { "post": { - "operationId": "incidentResolve", - "summary": "Resolve incident", - "description": "Close one or more incidents, optionally recording root cause, resolution, and resolution form values.", + "operationId": "incident-read-get-war-room-default-observers", + "summary": "Get war-room default observers", + "description": "Return people assigned to an incident earlier who are no longer responders, as suggested war-room observers.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- When a resolution form applies, `custom_fields`, `summary`, and `images` must match its visible elements and required rules.\n- For a batch, form values are accepted only when every selected incident resolves to the same form; otherwise resolve incidents individually.\n- The legacy `values` and `custom_values` properties are rejected; use `custom_fields`.\n- Incidents that are already closed are skipped without error; an unknown ID fails the whole call with `InvalidParameter`.\n- Resolving a `Triggered` incident first acknowledges it on behalf of the caller.\n- After closing, unfinished action items of the incident are converted to follow-ups, and later events no longer merge into the incident's existing alerts.\n- Returns `RequestTooFrequently` while another resolve, reopen, merge, comment, or delete is running in the same account; retry after a short delay.", - "href": "/en/api-reference/on-call/incidents/incident-resolve", + "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- Requires the On-call Pro license.\n- Observers are people who were assigned to or added as responders on the incident at some point (per its timeline) and are not current responders.\n- An empty `observers` array means there is no such person.\n- Returns `ResourceNotFound` when the incident does not exist.", + "href": "/en/api-reference/on-call/incidents/incident-read-get-war-room-default-observers", "metadata": { - "sidebarTitle": "Resolve incident" + "sidebarTitle": "Get war-room default observers" } }, "responses": { @@ -44943,7 +47266,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/GetWarRoomDefaultObserversResponse" } } } @@ -44951,7 +47274,21 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "observers": [ + { + "account_id": 2451002751131, + "person_id": 3790925372131, + "person_name": "Alice Chen", + "avatar": "https://example.com/avatars/3790925372131.png", + "email": "alice@example.com", + "locale": "zh-CN", + "time_zone": "Asia/Shanghai", + "as": "member", + "status": "enabled" + } + ] + } } } } @@ -44977,33 +47314,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResolveIncidentRequest" + "$ref": "#/components/schemas/GetWarRoomDefaultObserversRequest" }, "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee" - ], - "root_cause": "Memory leak in the connection pool caused by a missing cleanup call.", - "resolution": "Deployed hotfix v2.3.1 and restarted the affected service." + "incident_id": "69bb9233331067560c718ecd" } } } } } }, - "/incident/responder/add": { + "/incident/war-room/delete": { "post": { - "operationId": "incidentResponderAdd", - "summary": "Add incident responder", - "description": "Add members as responders to an open incident and notify them.", + "operationId": "incidentWarRoomDelete", + "summary": "Delete war room", + "description": "Dissolve an incident's war room group on the IM platform and unlink it from the incident.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Existing responders are kept, and IDs that are already responders are skipped. To replace the responder set, use `POST /incident/assign`.\n- Closed incidents are rejected with `InvalidParameter`.\n- Member IDs that do not exist in the account are ignored.\n- New responders are notified according to `notify`; by default each follows their personal notification preference.", - "href": "/en/api-reference/on-call/incidents/incident-responder-add", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The war room record is removed first; a failure to dissolve the group on the IM side (for example, it was already dissolved) is ignored.\n- Succeeds without changes when the incident has no war room on that integration.\n- To only unlink a war room whose IM integration is disabled or deleted, set `unlink_only: true` and pass its `chat_id`. This mode is limited to account owners and admins, fails with `InvalidParameter` while the integration is enabled, and does not dissolve the group.\n- On success the response has no `data` field.", + "href": "/en/api-reference/on-call/incidents/incident-war-room-delete", "metadata": { - "sidebarTitle": "Add incident responder" + "sidebarTitle": "Delete war room" } }, "responses": { @@ -45027,8 +47360,7 @@ ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } } @@ -45054,33 +47386,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AddIncidentResponderRequest" + "$ref": "#/components/schemas/DeleteWarRoomRequest" }, "example": { "incident_id": "69da451ef77b1b51f40e83ee", - "person_ids": [ - 2476444212131, - 2476444212132 - ] + "integration_id": 2490562293131 } } } } } }, - "/incident/sdp/request/list": { + "/incident/war-room/detail": { "post": { - "operationId": "incident-service-desk-plus-request-read-list", - "summary": "Get ServiceDeskPlus linked incidents", - "description": "List synchronization mappings between ServiceDeskPlus requests and Flashduty incidents.", + "operationId": "incidentWarRoomDetail", + "summary": "Get war room detail", + "description": "Fetch the current name and join link of a war room group from the IM platform.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Use this endpoint to inspect synchronization mappings between ServiceDeskPlus requests and Flashduty incidents, including the external request link and sync status.\n- When `incident_id` is not provided, `start_time` and `end_time` are required Unix-second timestamps; the time window cannot exceed 30 days.\n- `status` accepts only `success` and `failed`, representing successful and failed synchronization records.\n- Results are sorted by the internal record ID. Set `asc` to `true` for ascending order; otherwise records are returned descending.\n- Pagination uses only `search_after_ctx`: pass the value returned by the previous response; `p` is ignored.", - "href": "/en/api-reference/on-call/incidents/incident-service-desk-plus-request-read-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** (`on-call`) |\n\n## Usage\n\n- Supported for Feishu, DingTalk, WeCom, and Slack IM integrations; other integrations fail with `InvalidParameter`.\n- If the IM platform lookup fails (for example, the group was dissolved outside Flashduty), the call still succeeds and every field is an empty string.", + "href": "/en/api-reference/on-call/incidents/incident-war-room-detail", "metadata": { - "sidebarTitle": "Get ServiceDeskPlus linked incidents" + "sidebarTitle": "Get war room detail" } }, "responses": { @@ -45097,7 +47426,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ServiceDeskPlusRequestListResponse" + "$ref": "#/components/schemas/WarRoom" } } } @@ -45106,22 +47435,9 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [ - { - "created_at": 1779514631, - "status": "success", - "request_id": "100000000001", - "request_link": "https://servicedesk.example.com/app/itdesk/ui/requests/100000000001/details", - "integration_id": 98765, - "incident_id": "685d7f4e51b9a9a6d4d0c123", - "incident_title": "Checkout API 5xx rate increased", - "channel_id": 12345, - "channel_name": "Payments" - } - ], - "total": 1, - "has_next_page": false, - "search_after_ctx": "" + "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000", + "chat_name": "Incident #0E83EE war room", + "share_link": "" } } } @@ -45148,35 +47464,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServiceDeskPlusRequestListRequest" + "$ref": "#/components/schemas/GetWarRoomDetailRequest" }, "example": { - "start_time": 1779513600, - "end_time": 1779600000, - "status": "success", - "channel_ids": [ - 12345 - ], - "limit": 20 + "integration_id": 2490562293131, + "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000" } } } } } }, - "/incident/snooze": { + "/incident/war-room/list": { "post": { - "operationId": "incidentSnooze", - "summary": "Snooze incident", - "description": "Pause notifications for acknowledged incidents for a given number of minutes.", + "operationId": "incidentWarRoomList", + "summary": "List war rooms", + "description": "List the IM war room groups linked to an incident.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only incidents in `Processing` progress can be snoozed; any other progress fails the whole call with `InvalidParameter`.\n- Notifications resume automatically after `minutes` elapse, or earlier through `POST /incident/wake`. The snooze end time is stored in the incident's `snoozed_before` (Unix seconds).\n- The snooze is also cleared when the incident is reassigned or returns to `Triggered`.", - "href": "/en/api-reference/on-call/incidents/incident-snooze", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- War rooms whose IM integration is disabled or deleted are still returned, with `integration_unavailable` set to `true`.\n- Use `chat_id` and `integration_id` with `POST /incident/war-room/detail` to read the group's current name and join link.", + "href": "/en/api-reference/on-call/incidents/incident-war-room-list", "metadata": { - "sidebarTitle": "Snooze incident" + "sidebarTitle": "List war rooms" } }, "responses": { @@ -45193,7 +47504,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListWarRoomsResponse" } } } @@ -45201,7 +47512,21 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "items": [ + { + "account_id": 2451002751131, + "integration_id": 2490562293131, + "created_by": 2476444212131, + "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000", + "incident_id": "69da451ef77b1b51f40e83ee", + "status": "enabled", + "created_at": 1775972300, + "plugin_type": "feishu_app", + "chat_name": "Incident #0E83EE war room" + } + ] + } } } } @@ -45227,32 +47552,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SnoozeIncidentRequest" + "$ref": "#/components/schemas/ListWarRoomsRequest" }, "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee" - ], - "minutes": 60 + "incident_id": "69da451ef77b1b51f40e83ee" } } } } } }, - "/incident/unack": { + "/incident/work-item/assignees/reset": { "post": { - "operationId": "incidentUnack", - "summary": "Unacknowledge incident", - "description": "Withdraw the calling member's acknowledgement of one or more incidents.", + "operationId": "incidentWorkItemResetAssignees", + "summary": "Reset work item assignees", + "description": "Replace a work item's entire assignee set.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only the calling member's acknowledgement is removed. The incident returns to `Triggered`, and any snooze is cleared, only when no other responder still has it acknowledged.\n- Every incident must be in `Processing`; a `Triggered` or `Closed` incident fails the whole call with `InvalidParameter`.", - "href": "/en/api-reference/on-call/incidents/incident-unack", + "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- Requires the On-call Pro license.\n- Full replacement of the assignee set. Send `assignees` or the legacy `assignee_ids` (not both); omitting both returns an error, and `[]` or `null` clears all assignees.\n- Person assignees must be active members who can already read the incident or post-mortem — assignment never grants access.\n- Only newly added person assignees are notified; removals never notify. Newly adding `ai_sre` starts an AI SRE session for the item.\n- When the set does not change, `version` is not incremented.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- A `follow_up` item can be changed only while its incident is closed.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-reset-assignees", "metadata": { - "sidebarTitle": "Unacknowledge incident" + "sidebarTitle": "Reset work item assignees" } }, "responses": { @@ -45269,15 +47591,48 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/WorkItemMutationResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "data": { + "item": { + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "item_type": "action", + "incident_id": "6a5f1e28807515413b384bce", + "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", + "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", + "status": "in_progress", + "priority": "high", + "source_kind": "native", + "version": 3, + "assignee_ids": [ + 3790925372131, + 5068740052131 + ], + "assignees": [ + { + "type": "person", + "id": 3790925372131 + }, + { + "type": "person", + "id": 5068740052131 + } + ], + "created_by": 3790925372131, + "updated_by": 3790925372131, + "created_at_seconds": 1785496400, + "updated_at_seconds": 1785497000 + }, + "added_assignee_ids": [ + 5068740052131 + ] + } } } } @@ -45303,11 +47658,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UnackIncidentRequest" + "$ref": "#/components/schemas/ResetWorkItemAssigneesRequest" }, "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee" + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "version": 2, + "assignee_ids": [ + 3790925372131, + 5068740052131 ] } } @@ -45315,19 +47673,19 @@ } } }, - "/incident/wake": { + "/incident/work-item/complete": { "post": { - "operationId": "incidentWake", - "summary": "Wake incident", - "description": "End the snooze on incidents so that their notifications resume immediately.", + "operationId": "incidentWorkItemComplete", + "summary": "Complete a work item", + "description": "Mark a work item as done; only its current assignees can do this.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Incidents whose snooze has already ended are skipped; a closed incident fails the whole call with `InvalidParameter`.", - "href": "/en/api-reference/on-call/incidents/incident-wake", + "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- Requires the On-call Pro license.\n- `target_status` must be `done`.\n- Only a current person assignee can complete the item (account owners and admins are not implicit assignees); an item assigned to AI SRE can also be completed by the AI SRE session working on it. The caller also needs read access to the incident or post-mortem.\n- A `follow_up` item can be changed only while its incident is closed.\n- Repeating the call with the same `idempotency_key` returns the item with `idempotent_replay: true`.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-complete", "metadata": { - "sidebarTitle": "Wake incident" + "sidebarTitle": "Complete a work item" } }, "responses": { @@ -45344,15 +47702,40 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/WorkItemMutationResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "data": { + "item": { + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "item_type": "action", + "incident_id": "6a5f1e28807515413b384bce", + "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", + "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", + "status": "done", + "priority": "high", + "source_kind": "native", + "version": 3, + "assignee_ids": [ + 3790925372131 + ], + "assignees": [ + { + "type": "person", + "id": 3790925372131 + } + ], + "created_by": 3790925372131, + "updated_by": 3790925372131, + "created_at_seconds": 1785496400, + "updated_at_seconds": 1785497600 + } + } } } } @@ -45378,31 +47761,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/WakeIncidentRequest" + "$ref": "#/components/schemas/CompleteWorkItemRequest" }, "example": { - "incident_ids": [ - "69da451ef77b1b51f40e83ee" - ] + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "version": 2, + "target_status": "done", + "idempotency_key": "complete-wi-20260731-0001" } } } } } }, - "/incident/war-room/add-member": { + "/incident/work-item/convert": { "post": { - "operationId": "incident-write-add-war-room-member", - "summary": "Add war-room member", - "description": "Add members to an existing incident war room on Feishu (Lark), DingTalk, WeCom, or Slack.", + "operationId": "incidentWorkItemConvert", + "summary": "Convert a work item to a follow-up", + "description": "Convert an incident action item into a post-mortem follow-up in place.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the On-call Pro license.\n- `chat_id` must identify a war room created through Flashduty on integration `integration_id`; otherwise the call returns `ResourceNotFound`.\n- Only Feishu (Lark), DingTalk, WeCom and Slack integrations support war rooms; other integrations return `InvalidParameter`.\n- Every ID in `member_ids` must be a person in the account; one unknown ID fails the whole request.\n- On success `data` is the string `ok`.", - "href": "/en/api-reference/on-call/incidents/incident-write-add-war-room-member", + "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- Requires the On-call Pro license.\n- Converts an `action` into a post-mortem `follow_up` in place — the `work_item_id` does not change.\n- Converting an item that is already a `follow_up` changes nothing and returns `idempotent_replay: true`.\n- If the incident already has a post-mortem, the item is bound to it, which requires edit access to that report; otherwise bind it later with `POST /incident/work-item/post-mortem/bind`.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-convert", "metadata": { - "sidebarTitle": "Add war-room member" + "sidebarTitle": "Convert a work item to a follow-up" } }, "responses": { @@ -45419,16 +47803,43 @@ "type": "object", "properties": { "data": { - "type": "string", - "description": "Returns the literal \"ok\" on success." + "$ref": "#/components/schemas/WorkItemMutationResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": "ok" + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "data": { + "item": { + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "item_type": "follow_up", + "incident_id": "6a5f1e28807515413b384bce", + "post_mortem_id": "51d65cd9525c369379ba471b5512df63", + "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", + "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", + "status": "open", + "priority": "high", + "source_kind": "native", + "version": 3, + "assignee_ids": [ + 3790925372131 + ], + "assignees": [ + { + "type": "person", + "id": 3790925372131 + } + ], + "created_by": 3790925372131, + "updated_by": 3790925372131, + "converted_by": 3790925372131, + "converted_at_seconds": 1785497600, + "created_at_seconds": 1785496400, + "updated_at_seconds": 1785497600 + } + } } } } @@ -45454,34 +47865,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AddWarRoomMemberRequest" + "$ref": "#/components/schemas/ConvertWorkItemRequest" }, "example": { - "integration_id": 2551105804131, - "chat_id": "oc_5ce6d572455d361153b7cb51da133945", - "member_ids": [ - 3790925372131, - 5068740052131 - ] + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "version": 2, + "target_status": "open", + "idempotency_key": "convert-wi-20260731-0001" } } } } } }, - "/incident/war-room/create": { + "/incident/work-item/create": { "post": { - "operationId": "incidentWarRoomCreate", - "summary": "Create war room", - "description": "Create an IM group chat as the war room for an incident and invite members into it.", + "operationId": "incidentWorkItemCreate", + "summary": "Create a work item", + "description": "Create an action on an open incident, or a follow-up on a closed incident.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Professional edition or higher; otherwise the call fails with `NoLicense`.\n- The IM integration must be enabled with war room turned on. Feishu, DingTalk, WeCom (self-built app only), and Slack are supported.\n- An incident can have only one war room. Calling again with the same `integration_id` returns the existing group (with an empty `share_link`); a different `integration_id` fails with `InvalidParameter`.\n- A concurrent creation for the same incident returns `RequestTooFrequently`.\n- A successful creation adds an `i_wr_create` timeline entry.", - "href": "/en/api-reference/on-call/incidents/incident-war-room-create", + "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- Requires the On-call Pro license.\n- `action`: the incident must not be closed, the caller needs edit access to it, and `post_mortem_id` must be empty.\n- `follow_up`: the incident must be closed. With `post_mortem_id`, the caller needs edit access to that report and the incident must be linked to it. Without it, the caller needs edit access to the incident, and the server binds the incident's post-mortem if one exists; otherwise the item stays unbound until a report is created.\n- Set either `assignees` (entries `{type, id?}`; `type` is `person` or `ai_sre`, and an `ai_sre` entry omits `id`) or the legacy `assignee_ids` (all `person`), not both — sending both returns an error.\n- Person assignees must be active members who can already read the incident or post-mortem — assignment never grants access.\n- Newly added person assignees are notified; assigning `ai_sre` starts an AI SRE session that works on the item.\n- Retrying with the same `idempotency_key` from the same caller returns the original item with `idempotent_replay: true`; if that item was deleted, the call returns `RequestLocked`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-create", "metadata": { - "sidebarTitle": "Create war room" + "sidebarTitle": "Create a work item" } }, "responses": { @@ -45498,18 +47907,42 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/WarRoom" + "$ref": "#/components/schemas/WorkItemCreateResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", "data": { - "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000", - "chat_name": "Incident #0E83EE war room", - "share_link": "" + "item": { + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "item_type": "action", + "incident_id": "6a5f1e28807515413b384bce", + "title": "Roll back the v2.14 deployment on web-server-01", + "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", + "status": "open", + "priority": "high", + "source_kind": "native", + "version": 1, + "assignee_ids": [ + 3790925372131 + ], + "assignees": [ + { + "type": "person", + "id": 3790925372131 + } + ], + "created_by": 3790925372131, + "updated_by": 3790925372131, + "created_at_seconds": 1785496400, + "updated_at_seconds": 1785496400 + }, + "added_assignee_ids": [ + 3790925372131 + ] } } } @@ -45536,31 +47969,38 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateWarRoomRequest" + "$ref": "#/components/schemas/CreateWorkItemRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee", - "integration_id": 2490562293131, - "add_observers": true + "item_type": "action", + "title": "Roll back the v2.14 deployment on web-server-01", + "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", + "status": "open", + "priority": "high", + "incident_id": "6a5f1e28807515413b384bce", + "assignee_ids": [ + 3790925372131 + ], + "idempotency_key": "create-wi-20260731-0001" } } } } } }, - "/incident/war-room/default-observers": { + "/incident/work-item/delete": { "post": { - "operationId": "incident-read-get-war-room-default-observers", - "summary": "Get war-room default observers", - "description": "Return people assigned to an incident earlier who are no longer responders, as suggested war-room observers.", + "operationId": "incidentWorkItemDelete", + "summary": "Delete a work item", + "description": "Soft-delete a work item so it no longer appears in work item lists.", "tags": [ "On-call/Incidents" ], "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- Requires the On-call Pro license.\n- Observers are people who were assigned to or added as responders on the incident at some point (per its timeline) and are not current responders.\n- An empty `observers` array means there is no such person.\n- Returns `ResourceNotFound` when the incident does not exist.", - "href": "/en/api-reference/on-call/incidents/incident-read-get-war-room-default-observers", + "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- Requires the On-call Pro license.\n- Soft delete — the item no longer appears in listings but is retained; its create `idempotency_key` cannot be reused.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- A `follow_up` item can be changed only while its incident is closed.\n- On success `data` is an empty object.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-delete", "metadata": { - "sidebarTitle": "Get war-room default observers" + "sidebarTitle": "Delete a work item" } }, "responses": { @@ -45577,29 +48017,15 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/GetWarRoomDefaultObserversResponse" + "$ref": "#/components/schemas/WorkItemMutationResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "observers": [ - { - "account_id": 2451002751131, - "person_id": 3790925372131, - "person_name": "Alice Chen", - "avatar": "https://example.com/avatars/3790925372131.png", - "email": "alice@example.com", - "locale": "zh-CN", - "time_zone": "Asia/Shanghai", - "as": "member", - "status": "enabled" - } - ] - } + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "data": {} } } } @@ -45625,29 +48051,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetWarRoomDefaultObserversRequest" + "$ref": "#/components/schemas/DeleteWorkItemRequest" }, "example": { - "incident_id": "69bb9233331067560c718ecd" + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "version": 3 } } } } } }, - "/incident/war-room/delete": { + "/incident/work-item/list": { "post": { - "operationId": "incidentWarRoomDelete", - "summary": "Delete war room", - "description": "Dissolve an incident's war room group on the IM platform and unlink it from the incident.", + "operationId": "incidentWorkItemList", + "summary": "List work items", + "description": "List incident work items (actions and post-mortem follow-ups) with cursor pagination.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Incidents Manage** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The war room record is removed first; a failure to dissolve the group on the IM side (for example, it was already dissolved) is ignored.\n- Succeeds without changes when the incident has no war room on that integration.\n- To only unlink a war room whose IM integration is disabled or deleted, set `unlink_only: true` and pass its `chat_id`. This mode is limited to account owners and admins, fails with `InvalidParameter` while the integration is enabled, and does not dissolve the group.\n- On success the response has no `data` field.", - "href": "/en/api-reference/on-call/incidents/incident-war-room-delete", + "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- At least one of `incident_id`, `post_mortem_id`, `assignee_id`, or `assignee_type` = `ai_sre` is required.\n- Filtering by `incident_id` or `post_mortem_id` requires read access to that incident or report; listing by `incident_id` also includes follow-ups bound to the incident's post-mortem when the caller can read it.\n- Listing by `assignee_id` alone requires being that member or an account owner or admin. Without `incident_id` and `post_mortem_id`, callers who are not owner or admin see only items whose incident or report they can read.\n- Sorted by `updated_at_seconds` descending. Pass the previous response's `next_cursor` as `cursor` until `has_more` is false.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-list", "metadata": { - "sidebarTitle": "Delete war room" + "sidebarTitle": "List work items" } }, "responses": { @@ -45664,14 +48091,77 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/WorkItemListResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", + "item_type": "follow_up", + "incident_id": "6a5f1e28807515413b384bce", + "post_mortem_id": "51d65cd9525c369379ba471b5512df63", + "title": "Add a saturation alert for the orders database pool", + "status": "done", + "priority": "medium", + "source_kind": "native", + "version": 3, + "assignee_ids": [ + 3790925372131, + 5068740052131 + ], + "assignees": [ + { + "type": "person", + "id": 3790925372131 + }, + { + "type": "person", + "id": 5068740052131 + } + ], + "created_by": 4756301322131, + "updated_by": 3790925372131, + "converted_by": 4756301322131, + "converted_at_seconds": 1785495900, + "created_at_seconds": 1785495329, + "updated_at_seconds": 1785496384 + }, + { + "work_item_id": "wi_dMRYTeZHivE5vf87PQEeFX", + "item_type": "follow_up", + "incident_id": "6a5f1e28807515413b384bce", + "post_mortem_id": "51d65cd9525c369379ba471b5512df63", + "title": "Document the cache TTL rollback procedure", + "status": "open", + "priority": "low", + "source_kind": "native", + "version": 2, + "assignee_ids": [ + 5068740052131 + ], + "assignees": [ + { + "type": "person", + "id": 5068740052131 + } + ], + "created_by": 3790925372131, + "updated_by": 3790925372131, + "converted_by": 3790925372131, + "converted_at_seconds": 1785495200, + "created_at_seconds": 1785495164, + "updated_at_seconds": 1785495200 + } + ], + "next_cursor": "MTc4NTQ5NTIwMHx3aV9kTVJZVGVaSGl2RTV2Zjg3UFFFZUZY", + "has_more": true + } } } } @@ -45697,30 +48187,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeleteWarRoomRequest" + "$ref": "#/components/schemas/ListWorkItemRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee", - "integration_id": 2490562293131 + "incident_id": "6a5f1e28807515413b384bce", + "limit": 2 } } } } } }, - "/incident/war-room/detail": { + "/incident/work-item/post-mortem/bind": { "post": { - "operationId": "incidentWarRoomDetail", - "summary": "Get war room detail", - "description": "Fetch the current name and join link of a war room group from the IM platform.", + "operationId": "incidentWorkItemBindPostMortem", + "summary": "Bind work items to a post-mortem", + "description": "Bulk-bind an incident's converted-but-unbound follow-ups to a post-mortem.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** (`on-call`) |\n\n## Usage\n\n- Supported for Feishu, DingTalk, WeCom, and Slack IM integrations; other integrations fail with `InvalidParameter`.\n- If the IM platform lookup fails (for example, the group was dissolved outside Flashduty), the call still succeeds and every field is an empty string.", - "href": "/en/api-reference/on-call/incidents/incident-war-room-detail", + "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- Requires the On-call Pro license.\n- Binds every item of the incident that was converted from an action and is not yet bound to any post-mortem.\n- The caller needs edit access to the post-mortem, and `incident_id` must be linked to it.\n- `items` holds the items bound by this call and may be empty; `next_cursor` is not set and `has_more` is false.\n- Retrying with the same `idempotency_key` returns the items bound earlier with `idempotent_replay: true`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-bind-post-mortem", "metadata": { - "sidebarTitle": "Get war room detail" + "sidebarTitle": "Bind work items to a post-mortem" } }, "responses": { @@ -45737,18 +48227,75 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/WarRoom" + "$ref": "#/components/schemas/WorkItemListResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", "data": { - "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000", - "chat_name": "Incident #0E83EE war room", - "share_link": "" + "items": [ + { + "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", + "item_type": "follow_up", + "incident_id": "6a5f1e28807515413b384bce", + "post_mortem_id": "51d65cd9525c369379ba471b5512df63", + "title": "Add a saturation alert for the orders database pool", + "status": "done", + "priority": "medium", + "source_kind": "native", + "version": 3, + "assignee_ids": [ + 3790925372131, + 5068740052131 + ], + "assignees": [ + { + "type": "person", + "id": 3790925372131 + }, + { + "type": "person", + "id": 5068740052131 + } + ], + "created_by": 4756301322131, + "updated_by": 3790925372131, + "converted_by": 4756301322131, + "converted_at_seconds": 1785495900, + "created_at_seconds": 1785495329, + "updated_at_seconds": 1785496384 + }, + { + "work_item_id": "wi_dMRYTeZHivE5vf87PQEeFX", + "item_type": "follow_up", + "incident_id": "6a5f1e28807515413b384bce", + "post_mortem_id": "51d65cd9525c369379ba471b5512df63", + "title": "Document the cache TTL rollback procedure", + "status": "open", + "priority": "low", + "source_kind": "native", + "version": 2, + "assignee_ids": [ + 5068740052131 + ], + "assignees": [ + { + "type": "person", + "id": 5068740052131 + } + ], + "created_by": 3790925372131, + "updated_by": 3790925372131, + "converted_by": 3790925372131, + "converted_at_seconds": 1785495200, + "created_at_seconds": 1785495164, + "updated_at_seconds": 1785495200 + } + ], + "has_more": false } } } @@ -45775,30 +48322,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/GetWarRoomDetailRequest" + "$ref": "#/components/schemas/BindWorkItemPostMortemRequest" }, "example": { - "integration_id": 2490562293131, - "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000" + "post_mortem_id": "51d65cd9525c369379ba471b5512df63", + "incident_id": "6a5f1e28807515413b384bce", + "idempotency_key": "bind-wi-20260731-0001" } } } } } }, - "/incident/war-room/list": { + "/incident/work-item/update": { "post": { - "operationId": "incidentWarRoomList", - "summary": "List war rooms", - "description": "List the IM war room groups linked to an incident.", + "operationId": "incidentWorkItemUpdate", + "summary": "Update a work item", + "description": "Partially update a work item's title, description, status, or priority.", "tags": [ "On-call/Incidents" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Incidents Read** or **Incidents Manage** or **Channels Read** or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- War rooms whose IM integration is disabled or deleted are still returned, with `integration_unavailable` set to `true`.\n- Use `chat_id` and `integration_id` with `POST /incident/war-room/detail` to read the group's current name and join link.", - "href": "/en/api-reference/on-call/incidents/incident-war-room-list", + "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- Requires the On-call Pro license.\n- Partial patch: omitted fields and fields sent as `null` stay unchanged. Send `\"\"` to clear `description` or `priority`; `title` and `status` cannot be empty.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- When nothing would change, the current item is returned without checking `version` and without incrementing it.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- A `follow_up` item can be changed only while its incident is closed.\n- Assignees, `item_type`, and the incident/post-mortem anchors cannot be changed here — use the dedicated endpoints.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/incidents/incident-work-item-update", "metadata": { - "sidebarTitle": "List war rooms" + "sidebarTitle": "Update a work item" } }, "responses": { @@ -45815,28 +48363,39 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListWarRoomsResponse" + "$ref": "#/components/schemas/WorkItemMutationResult" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [ - { - "account_id": 2451002751131, - "integration_id": 2490562293131, - "created_by": 2476444212131, - "chat_id": "oc_a0553eda9014c2de1b3a8f75b4e0c000", - "incident_id": "69da451ef77b1b51f40e83ee", - "status": "enabled", - "created_at": 1775972300, - "plugin_type": "feishu_app", - "chat_name": "Incident #0E83EE war room" - } - ] + "item": { + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "item_type": "action", + "incident_id": "6a5f1e28807515413b384bce", + "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", + "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", + "status": "in_progress", + "priority": "high", + "source_kind": "native", + "version": 2, + "assignee_ids": [ + 3790925372131 + ], + "assignees": [ + { + "type": "person", + "id": 3790925372131 + } + ], + "created_by": 3790925372131, + "updated_by": 3790925372131, + "created_at_seconds": 1785496400, + "updated_at_seconds": 1785496700 + } } } } @@ -45863,29 +48422,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListWarRoomsRequest" + "$ref": "#/components/schemas/UpdateWorkItemRequest" }, "example": { - "incident_id": "69da451ef77b1b51f40e83ee" + "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", + "version": 1, + "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", + "status": "in_progress" } } } } } }, - "/incident/work-item/assignees/reset": { + "/insight/account": { "post": { - "operationId": "incidentWorkItemResetAssignees", - "summary": "Reset work item assignees", - "description": "Replace a work item's entire assignee set.", + "operationId": "insightByAccount", + "summary": "Get account-level insight", + "description": "Return incident and alert metrics for the whole account, one row per time bucket.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- Requires the On-call Pro license.\n- Full replacement of the assignee set. Send `assignees` or the legacy `assignee_ids` (not both); omitting both returns an error, and `[]` or `null` clears all assignees.\n- Person assignees must be active members who can already read the incident or post-mortem — assignment never grants access.\n- Only newly added person assignees are notified; removals never notify. Newly adding `ai_sre` starts an AI SRE session for the item.\n- When the set does not change, `version` is not incremented.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- A `follow_up` item can be changed only while its incident is closed.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-reset-assignees", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per time bucket for the whole account. `responder_ids` and `incident_ids` are ignored; use `/insight/responder` or `/insight/incident/list` for those.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- `total_alert_cnt`, `total_alert_event_cnt` and `noise_reduction_pct` honor only the time range, team, channel and severity filters; `query`, `labels`, `fields` and the duration filters apply to incident metrics only.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", + "href": "/en/api-reference/on-call/analytics/insight-by-account", "metadata": { - "sidebarTitle": "Reset work item assignees" + "sidebarTitle": "Get account-level insight" } }, "responses": { @@ -45902,46 +48464,40 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/WorkItemMutationResult" + "$ref": "#/components/schemas/DimensionInsightResponse" } } } ] }, "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "item": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "item_type": "action", - "incident_id": "6a5f1e28807515413b384bce", - "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", - "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", - "status": "in_progress", - "priority": "high", - "source_kind": "native", - "version": 3, - "assignee_ids": [ - 3790925372131, - 5068740052131 - ], - "assignees": [ - { - "type": "person", - "id": 3790925372131 - }, - { - "type": "person", - "id": 5068740052131 - } - ], - "created_by": 3790925372131, - "updated_by": 3790925372131, - "created_at_seconds": 1785496400, - "updated_at_seconds": 1785497000 - }, - "added_assignee_ids": [ - 5068740052131 + "items": [ + { + "ts": 1740844800, + "total_incident_cnt": 2, + "total_incidents_acknowledged": 2, + "total_incidents_closed": 2, + "total_incidents_auto_closed": 0, + "total_incidents_manually_closed": 2, + "total_incidents_timeout_closed": 0, + "total_incidents_escalated": 0, + "total_incidents_manually_escalated": 0, + "total_incidents_timeout_escalated": 0, + "total_incidents_reassigned": 2, + "total_interruptions": 3, + "total_notifications": 6, + "total_engaged_seconds": 3317709, + "total_seconds_to_ack": 3317709, + "total_seconds_to_close": 3749514, + "mean_seconds_to_ack": 1658854.5, + "mean_seconds_to_close": 1874757, + "noise_reduction_pct": 0, + "acknowledgement_pct": 100, + "total_alert_cnt": 0, + "total_alert_event_cnt": 0 + } ] } } @@ -45969,14 +48525,15 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResetWorkItemAssigneesRequest" + "$ref": "#/components/schemas/InsightQueryRequest" }, "example": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "version": 2, - "assignee_ids": [ - 3790925372131, - 5068740052131 + "start_time": 1712000000, + "end_time": 1712604800, + "aggregate_unit": "day", + "severities": [ + "Critical", + "Warning" ] } } @@ -45984,19 +48541,19 @@ } } }, - "/incident/work-item/complete": { + "/insight/alert/topk-by-label": { "post": { - "operationId": "incidentWorkItemComplete", - "summary": "Complete a work item", - "description": "Mark a work item as done; only its current assignees can do this.", + "operationId": "insightTopkAlertsByLabel", + "summary": "Get top-K alerts grouped by check or resource", + "description": "Return the top-K alert groups aggregated either by `check` or by `resource` label over the specified time range.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- Requires the On-call Pro license.\n- `target_status` must be `done`.\n- Only a current person assignee can complete the item (account owners and admins are not implicit assignees); an item assigned to AI SRE can also be completed by the AI SRE session working on it. The caller also needs read access to the incident or post-mortem.\n- A `follow_up` item can be changed only while its incident is closed.\n- Repeating the call with the same `idempotency_key` returns the item with `idempotent_replay: true`.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-complete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- Only the time range, `team_ids`, `channel_ids`, `severities`, `is_my_team` and `split_hours` filter the result; other filter fields and `aggregate_unit` are ignored.\n- Alerts are counted in hourly buckets, so the effective range is aligned to whole hours.\n- With `split_hours: true`, the top `k` is computed separately for each of `work`, `sleep` and `off`, so up to 3 × `k` rows come back.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.", + "href": "/en/api-reference/on-call/analytics/insight-topk-alerts-by-label", "metadata": { - "sidebarTitle": "Complete a work item" + "sidebarTitle": "Get top-K alerts grouped by check or resource" } }, "responses": { @@ -46013,39 +48570,32 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/WorkItemMutationResult" + "$ref": "#/components/schemas/InsightAlertByLabelResponse" } } } ] }, "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "item": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "item_type": "action", - "incident_id": "6a5f1e28807515413b384bce", - "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", - "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", - "status": "done", - "priority": "high", - "source_kind": "native", - "version": 3, - "assignee_ids": [ - 3790925372131 - ], - "assignees": [ - { - "type": "person", - "id": 3790925372131 - } - ], - "created_by": 3790925372131, - "updated_by": 3790925372131, - "created_at_seconds": 1785496400, - "updated_at_seconds": 1785497600 - } + "items": [ + { + "label": "cpu-high", + "total_alert_cnt": 312, + "total_alert_event_cnt": 987 + }, + { + "label": "disk-full", + "total_alert_cnt": 178, + "total_alert_event_cnt": 452 + }, + { + "label": "memory-oom", + "total_alert_cnt": 94, + "total_alert_event_cnt": 231 + } + ] } } } @@ -46072,32 +48622,33 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CompleteWorkItemRequest" + "$ref": "#/components/schemas/InsightTopkAlertByLabelRequest" }, "example": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "version": 2, - "target_status": "done", - "idempotency_key": "complete-wi-20260731-0001" + "start_time": 1712000000, + "end_time": 1712604800, + "label": "check", + "k": 10, + "orderby": "total_alert_cnt" } } } } } }, - "/incident/work-item/convert": { + "/insight/channel": { "post": { - "operationId": "incidentWorkItemConvert", - "summary": "Convert a work item to a follow-up", - "description": "Convert an incident action item into a post-mortem follow-up in place.", + "operationId": "insightByChannel", + "summary": "Get channel insight", + "description": "Return incident and alert metrics grouped by channel, one row per channel per time bucket.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- Requires the On-call Pro license.\n- Converts an `action` into a post-mortem `follow_up` in place — the `work_item_id` does not change.\n- Converting an item that is already a `follow_up` changes nothing and returns `idempotent_replay: true`.\n- If the incident already has a post-mortem, the item is bound to it, which requires edit access to that report; otherwise bind it later with `POST /incident/work-item/post-mortem/bind`.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-convert", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per channel per time bucket. `responder_ids` and `incident_ids` are ignored.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- `total_alert_cnt`, `total_alert_event_cnt` and `noise_reduction_pct` honor only the time range, team, channel and severity filters; `query`, `labels`, `fields` and the duration filters apply to incident metrics only.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", + "href": "/en/api-reference/on-call/analytics/insight-by-channel", "metadata": { - "sidebarTitle": "Convert a work item to a follow-up" + "sidebarTitle": "Get channel insight" } }, "responses": { @@ -46114,42 +48665,43 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/WorkItemMutationResult" + "$ref": "#/components/schemas/DimensionInsightResponse" } } } ] }, "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "item": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "item_type": "follow_up", - "incident_id": "6a5f1e28807515413b384bce", - "post_mortem_id": "51d65cd9525c369379ba471b5512df63", - "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", - "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", - "status": "open", - "priority": "high", - "source_kind": "native", - "version": 3, - "assignee_ids": [ - 3790925372131 - ], - "assignees": [ - { - "type": "person", - "id": 3790925372131 - } - ], - "created_by": 3790925372131, - "updated_by": 3790925372131, - "converted_by": 3790925372131, - "converted_at_seconds": 1785497600, - "created_at_seconds": 1785496400, - "updated_at_seconds": 1785497600 - } + "items": [ + { + "ts": 1740844800, + "channel_id": 4321322010131, + "channel_name": "Production Alerts", + "total_incident_cnt": 2, + "total_incidents_acknowledged": 2, + "total_incidents_closed": 2, + "total_incidents_auto_closed": 0, + "total_incidents_manually_closed": 2, + "total_incidents_timeout_closed": 0, + "total_incidents_escalated": 0, + "total_incidents_manually_escalated": 0, + "total_incidents_timeout_escalated": 0, + "total_incidents_reassigned": 2, + "total_interruptions": 3, + "total_notifications": 6, + "total_engaged_seconds": 3317709, + "total_seconds_to_ack": 3317709, + "total_seconds_to_close": 3749514, + "mean_seconds_to_ack": 1658854.5, + "mean_seconds_to_close": 1874757, + "noise_reduction_pct": 0, + "acknowledgement_pct": 100, + "total_alert_cnt": 0, + "total_alert_event_cnt": 0 + } + ] } } } @@ -46176,86 +48728,47 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ConvertWorkItemRequest" + "$ref": "#/components/schemas/InsightQueryRequest" }, "example": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "version": 2, - "target_status": "open", - "idempotency_key": "convert-wi-20260731-0001" + "start_time": 1712000000, + "end_time": 1712604800, + "channel_ids": [ + 4321322010131 + ], + "aggregate_unit": "day" } } } } } }, - "/incident/work-item/create": { + "/insight/channel/export": { "post": { - "operationId": "incidentWorkItemCreate", - "summary": "Create a work item", - "description": "Create an action on an open incident, or a follow-up on a closed incident.", + "operationId": "insightChannelExport", + "summary": "Export channel insight", + "description": "Export channel insight metrics as a CSV file with the same rows as `/insight/channel`.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- Requires the On-call Pro license.\n- `action`: the incident must not be closed, the caller needs edit access to it, and `post_mortem_id` must be empty.\n- `follow_up`: the incident must be closed. With `post_mortem_id`, the caller needs edit access to that report and the incident must be linked to it. Without it, the caller needs edit access to the incident, and the server binds the incident's post-mortem if one exists; otherwise the item stays unbound until a report is created.\n- Set either `assignees` (entries `{type, id?}`; `type` is `person` or `ai_sre`, and an `ai_sre` entry omits `id`) or the legacy `assignee_ids` (all `person`), not both — sending both returns an error.\n- Person assignees must be active members who can already read the incident or post-mortem — assignment never grants access.\n- Newly added person assignees are notified; assigning `ai_sre` starts an AI SRE session that works on the item.\n- Retrying with the same `idempotency_key` from the same caller returns the original item with `idempotent_replay: true`; if that item was deleted, the call returns `RequestLocked`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters as `/insight/channel`. Rows without a channel ID are skipped. The file has no time-bucket column, so with `aggregate_unit` the rows of different buckets cannot be told apart; export one bucket per request if you need the split.\n- `export_fields` sets the columns and their order: channel_id, channel_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_closed, total_incidents_auto_closed, total_incidents_manually_closed, total_incidents_timeout_closed, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_incidents_reassigned, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, mean_seconds_to_close, noise_reduction_pct, acknowledgement_pct, total_alert_cnt, total_alert_event_cnt, hours. Unknown or duplicate keys are rejected. When it is omitted, all columns are exported, and `hours` is included only when `split_hours` is true.\n- The incident-snapshot keys (progress, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, ackers, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, snooze_status, snoozed_before, ever_muted, frequency, is_rare, alert_cnt, active_alert_cnt, alert_event_cnt, description, labels, fields) are also accepted for compatibility and produce empty columns.\n- Column headers are localized (request locale, then the member's, then the account's). Time buckets follow `time_zone` (UTC when omitted).", + "href": "/en/api-reference/on-call/analytics/insight-channel-export", "metadata": { - "sidebarTitle": "Create a work item" + "sidebarTitle": "Export channel insight" } }, "responses": { "200": { "description": "Success", "content": { - "application/json": { + "application/octet-stream": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/components/schemas/WorkItemCreateResult" - } - } - } - ] + "type": "string", + "format": "binary", + "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''channel_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." }, - "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", - "data": { - "item": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "item_type": "action", - "incident_id": "6a5f1e28807515413b384bce", - "title": "Roll back the v2.14 deployment on web-server-01", - "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", - "status": "open", - "priority": "high", - "source_kind": "native", - "version": 1, - "assignee_ids": [ - 3790925372131 - ], - "assignees": [ - { - "type": "person", - "id": 3790925372131 - } - ], - "created_by": 3790925372131, - "updated_by": 3790925372131, - "created_at_seconds": 1785496400, - "updated_at_seconds": 1785496400 - }, - "added_assignee_ids": [ - 3790925372131 - ] - } - } + "example": "channel_id,channel_name,total_incident_cnt,total_incidents_closed\n4321322010131,Production Alerts,12,10\n" } } }, @@ -46280,64 +48793,50 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateWorkItemRequest" + "$ref": "#/components/schemas/InsightQueryRequest" }, "example": { - "item_type": "action", - "title": "Roll back the v2.14 deployment on web-server-01", - "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", - "status": "open", - "priority": "high", - "incident_id": "6a5f1e28807515413b384bce", - "assignee_ids": [ - 3790925372131 + "start_time": 1712000000, + "end_time": 1712604800, + "channel_ids": [ + 4321322010131 ], - "idempotency_key": "create-wi-20260731-0001" + "severities": [ + "Critical", + "Warning" + ] } } } } } }, - "/incident/work-item/delete": { + "/insight/incident/export": { "post": { - "operationId": "incidentWorkItemDelete", - "summary": "Delete a work item", - "description": "Soft-delete a work item so it no longer appears in work item lists.", + "operationId": "insightIncidentExport", + "summary": "Export insight incidents", + "description": "Export the incidents matched by the analytics filters as a CSV file, one row per incident.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- Requires the On-call Pro license.\n- Soft delete — the item no longer appears in listings but is retained; its create `idempotency_key` cannot be reused.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- A `follow_up` item can be changed only while its incident is closed.\n- On success `data` is an empty object.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters and sort order as `/insight/incident/list`. Export stops once more than 100,000 rows have been written.\n- `start_time` is moved forward to the earliest date kept by the account's data retention; a range that ends before that date is rejected.\n- `export_fields` sets the columns and their order: incident_id, title, severity, progress, channel_id, channel_name, team_id, team_name, created_at, alert_cnt, active_alert_cnt, alert_event_cnt, seconds_to_ack, seconds_to_close, closed_by, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, engaged_seconds, hours, notifications, interruptions, acknowledgements, ackers, assignments, reassignments, escalations, manual_escalations, timeout_escalations, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, snooze_status, snoozed_before, ever_muted, frequency, is_rare, description, labels, fields. Unknown or duplicate keys are rejected; when omitted, every column except the aliases `owner_id`, `creator_id`, `closer_id`, `snoozed_before` and `is_rare` is exported.\n- `description_html_to_text: true` strips HTML from the `description` column.\n- Headers and formatted values use the request locale, then the member's, then the account's. Times are rendered in `time_zone`, falling back to the account time zone and then `Asia/Shanghai`.", + "href": "/en/api-reference/on-call/analytics/insight-incident-export", "metadata": { - "sidebarTitle": "Delete a work item" + "sidebarTitle": "Export insight incidents" } }, "responses": { "200": { "description": "Success", "content": { - "application/json": { + "application/octet-stream": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/components/schemas/WorkItemMutationResult" - } - } - } - ] + "type": "string", + "format": "binary", + "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''incident_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." }, - "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", - "data": {} - } + "example": "incident_id,title,severity,created_at\n6a86b5d6f72de50ae1ce2ffb,CPU usage above 90%,Critical,2026-01-01 10:00:00 +0800 CST\n" } } }, @@ -46362,30 +48861,42 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DeleteWorkItemRequest" + "$ref": "#/components/schemas/InsightIncidentExportRequest" }, "example": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "version": 3 + "start_time": 1712000000, + "end_time": 1712604800, + "severities": [ + "Critical", + "Warning" + ], + "export_fields": [ + "incident_id", + "title", + "severity", + "created_at", + "seconds_to_close" + ], + "description_html_to_text": true } } } } } }, - "/incident/work-item/list": { + "/insight/incident/list": { "post": { - "operationId": "incidentWorkItemList", - "summary": "List work items", - "description": "List incident work items (actions and post-mortem follow-ups) with cursor pagination.", + "operationId": "insightIncidentList", + "summary": "List insight incidents", + "description": "Return a paged list of incidents with per-incident handling metrics used by the analytics dashboard.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- At least one of `incident_id`, `post_mortem_id`, `assignee_id`, or `assignee_type` = `ai_sre` is required.\n- Filtering by `incident_id` or `post_mortem_id` requires read access to that incident or report; listing by `incident_id` also includes follow-ups bound to the incident's post-mortem when the caller can read it.\n- Listing by `assignee_id` alone requires being that member or an account owner or admin. Without `incident_id` and `post_mortem_id`, callers who are not owner or admin see only items whose incident or report they can read.\n- Sorted by `updated_at_seconds` descending. Pass the previous response's `next_cursor` as `cursor` until `has_more` is false.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- Sorted by incident creation time, newest first by default (`asc: true` for oldest first).\n- Page with `p` + `limit` (at most 10,000 records reachable) or, for deeper reads, pass the previous page's `search_after_ctx` back. When `search_after_ctx` is sent, `total` counts only the incidents after the cursor.\n- `responder_ids` keeps incidents in which any of the given members was a responder.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", + "href": "/en/api-reference/on-call/analytics/insight-incident-list", "metadata": { - "sidebarTitle": "List work items" + "sidebarTitle": "List insight incidents" } }, "responses": { @@ -46402,76 +48913,69 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/WorkItemListResult" + "$ref": "#/components/schemas/InsightIncidentListResponse" } } } ] }, "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { + "total": 2363, + "has_next_page": true, + "search_after_ctx": "6a86b5d6f72de50ae1ce2ffb", "items": [ { - "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", - "item_type": "follow_up", - "incident_id": "6a5f1e28807515413b384bce", - "post_mortem_id": "51d65cd9525c369379ba471b5512df63", - "title": "Add a saturation alert for the orders database pool", - "status": "done", - "priority": "medium", - "source_kind": "native", - "version": 3, - "assignee_ids": [ - 3790925372131, - 5068740052131 - ], - "assignees": [ - { - "type": "person", - "id": 3790925372131 - }, - { - "type": "person", - "id": 5068740052131 - } - ], - "created_by": 4756301322131, - "updated_by": 3790925372131, - "converted_by": 4756301322131, - "converted_at_seconds": 1785495900, - "created_at_seconds": 1785495329, - "updated_at_seconds": 1785496384 - }, - { - "work_item_id": "wi_dMRYTeZHivE5vf87PQEeFX", - "item_type": "follow_up", - "incident_id": "6a5f1e28807515413b384bce", - "post_mortem_id": "51d65cd9525c369379ba471b5512df63", - "title": "Document the cache TTL rollback procedure", - "status": "open", - "priority": "low", - "source_kind": "native", - "version": 2, - "assignee_ids": [ - 5068740052131 - ], - "assignees": [ + "incident_id": "6a86b5d6f72de50ae1ce2ffb", + "title": "CPU usage above 90% on prod-web-01", + "description": "CPU usage stayed above the threshold for 5 minutes", + "team_id": 2477033058131, + "team_name": "SRE Team", + "channel_id": 3047621227131, + "channel_name": "Production Alerts", + "progress": "Closed", + "severity": "Critical", + "created_at": 1787213270, + "alert_cnt": 3, + "active_alert_cnt": 0, + "alert_event_cnt": 5, + "closed_by": "manually", + "creator_id": 2477273692131, + "creator_name": "alice", + "closer_id": 2477273692131, + "closer_name": "alice", + "seconds_to_ack": 14, + "seconds_to_close": 1830, + "engaged_seconds": 1816, + "hours": "work", + "responders": [ { - "type": "person", - "id": 5068740052131 + "person_id": 2477273692131, + "assigned_at": 1787213270, + "acknowledged_at": 1787213284, + "person_name": "alice", + "email": "alice@example.com" } ], - "created_by": 3790925372131, - "updated_by": 3790925372131, - "converted_by": 3790925372131, - "converted_at_seconds": 1785495200, - "created_at_seconds": 1785495164, - "updated_at_seconds": 1785495200 - } - ], - "next_cursor": "MTc4NTQ5NTIwMHx3aV9kTVJZVGVaSGl2RTV2Zjg3UFFFZUZY", - "has_more": true + "assigned_to": { + "escalate_rule_id": "66138789904a9027583dbc4e", + "layer_idx": 0, + "type": "assign", + "assigned_at": 1787213270, + "id": "b8tyUoRvCv4wsPndFRpmNL", + "escalate_rule_name": "On-call Policy" + }, + "notifications": 2, + "interruptions": 1, + "assignments": 1, + "reassignments": 0, + "acknowledgements": 1, + "escalations": 0, + "timeout_escalations": 0, + "manual_escalations": 0 + } + ] } } } @@ -46498,30 +49002,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListWorkItemRequest" + "$ref": "#/components/schemas/InsightIncidentListRequest" }, "example": { - "incident_id": "6a5f1e28807515413b384bce", - "limit": 2 + "start_time": 1712000000, + "end_time": 1712604800, + "p": 1, + "limit": 20, + "severities": [ + "Critical" + ] } } } } } }, - "/incident/work-item/post-mortem/bind": { + "/insight/responder": { "post": { - "operationId": "incidentWorkItemBindPostMortem", - "summary": "Bind work items to a post-mortem", - "description": "Bulk-bind an incident's converted-but-unbound follow-ups to a post-mortem.", + "operationId": "insightByResponder", + "summary": "Get responder insight", + "description": "Return per-responder incident handling metrics, one row per responder per time bucket.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- Requires the On-call Pro license.\n- Binds every item of the incident that was converted from an action and is not yet bound to any post-mortem.\n- The caller needs edit access to the post-mortem, and `incident_id` must be linked to it.\n- `items` holds the items bound by this call and may be empty; `next_cursor` is not set and `has_more` is false.\n- Retrying with the same `idempotency_key` returns the items bound earlier with `idempotent_replay: true`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-bind-post-mortem", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per responder per time bucket; `responder_ids` limits which responders are returned. `seconds_to_close_from`/`seconds_to_close_to` and `incident_ids` are ignored.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", + "href": "/en/api-reference/on-call/analytics/insight-by-responder", "metadata": { - "sidebarTitle": "Bind work items to a post-mortem" + "sidebarTitle": "Get responder insight" } }, "responses": { @@ -46538,75 +49047,34 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/WorkItemListResult" + "$ref": "#/components/schemas/ResponderInsightResponse" } } } ] }, "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "items": [ { - "work_item_id": "wi_68MHnkWBiyjrh6uhkxUyiZ", - "item_type": "follow_up", - "incident_id": "6a5f1e28807515413b384bce", - "post_mortem_id": "51d65cd9525c369379ba471b5512df63", - "title": "Add a saturation alert for the orders database pool", - "status": "done", - "priority": "medium", - "source_kind": "native", - "version": 3, - "assignee_ids": [ - 3790925372131, - 5068740052131 - ], - "assignees": [ - { - "type": "person", - "id": 3790925372131 - }, - { - "type": "person", - "id": 5068740052131 - } - ], - "created_by": 4756301322131, - "updated_by": 3790925372131, - "converted_by": 4756301322131, - "converted_at_seconds": 1785495900, - "created_at_seconds": 1785495329, - "updated_at_seconds": 1785496384 - }, - { - "work_item_id": "wi_dMRYTeZHivE5vf87PQEeFX", - "item_type": "follow_up", - "incident_id": "6a5f1e28807515413b384bce", - "post_mortem_id": "51d65cd9525c369379ba471b5512df63", - "title": "Document the cache TTL rollback procedure", - "status": "open", - "priority": "low", - "source_kind": "native", - "version": 2, - "assignee_ids": [ - 5068740052131 - ], - "assignees": [ - { - "type": "person", - "id": 5068740052131 - } - ], - "created_by": 3790925372131, - "updated_by": 3790925372131, - "converted_by": 3790925372131, - "converted_at_seconds": 1785495200, - "created_at_seconds": 1785495164, - "updated_at_seconds": 1785495200 + "ts": 1740844800, + "responder_id": 3790925372131, + "responder_name": "alice", + "total_incident_cnt": 1, + "total_incidents_acknowledged": 1, + "total_incidents_reassigned": 0, + "total_incidents_escalated": 0, + "total_incidents_timeout_escalated": 0, + "total_incidents_manually_escalated": 0, + "total_interruptions": 1, + "total_notifications": 2, + "total_engaged_seconds": 10, + "total_seconds_to_ack": 2265624, + "mean_seconds_to_ack": 2265624, + "acknowledgement_pct": 100 } - ], - "has_more": false + ] } } } @@ -46633,82 +49101,47 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BindWorkItemPostMortemRequest" + "$ref": "#/components/schemas/InsightQueryRequest" }, "example": { - "post_mortem_id": "51d65cd9525c369379ba471b5512df63", - "incident_id": "6a5f1e28807515413b384bce", - "idempotency_key": "bind-wi-20260731-0001" + "start_time": 1712000000, + "end_time": 1712604800, + "responder_ids": [ + 3790925372131 + ], + "aggregate_unit": "day" } } } } } }, - "/incident/work-item/update": { + "/insight/responder/export": { "post": { - "operationId": "incidentWorkItemUpdate", - "summary": "Update a work item", - "description": "Partially update a work item's title, description, status, or priority.", + "operationId": "insightResponderExport", + "summary": "Export responder insight", + "description": "Export responder insight metrics as a CSV file with the same rows as `/insight/responder`.", "tags": [ - "On-call/Incidents" + "On-call/Analytics" ], "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- Requires the On-call Pro license.\n- Partial patch: omitted fields and fields sent as `null` stay unchanged. Send `\"\"` to clear `description` or `priority`; `title` and `status` cannot be empty.\n- Optimistic locking — `version` must equal the item's current version; a mismatch returns `RequestLocked` (HTTP 423). Re-read the item and retry.\n- When nothing would change, the current item is returned without checking `version` and without incrementing it.\n- The caller needs edit access to the item's anchor: the post-mortem when the item is bound to one, otherwise the incident.\n- A `follow_up` item can be changed only while its incident is closed.\n- Assignees, `item_type`, and the incident/post-mortem anchors cannot be changed here — use the dedicated endpoints.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/incidents/incident-work-item-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters as `/insight/responder`. Rows without a responder ID are skipped. The file has no time-bucket column, so with `aggregate_unit` the rows of different buckets cannot be told apart; export one bucket per request if you need the split.\n- `export_fields` sets the columns and their order: responder_id, responder_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_reassigned, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, acknowledgement_pct, hours. Unknown or duplicate keys are rejected. When it is omitted, all columns are exported, and `hours` is included only when `split_hours` is true.\n- The incident-snapshot keys (progress, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, ackers, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, snooze_status, snoozed_before, ever_muted, frequency, is_rare, alert_cnt, active_alert_cnt, alert_event_cnt, description, labels, fields) are also accepted for compatibility and produce empty columns.\n- Column headers are localized (request locale, then the member's, then the account's). Time buckets follow `time_zone` (UTC when omitted).", + "href": "/en/api-reference/on-call/analytics/insight-responder-export", "metadata": { - "sidebarTitle": "Update a work item" + "sidebarTitle": "Export responder insight" } }, "responses": { "200": { "description": "Success", "content": { - "application/json": { + "application/octet-stream": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/components/schemas/WorkItemMutationResult" - } - } - } - ] + "type": "string", + "format": "binary", + "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''responder_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." }, - "example": { - "request_id": "01J8XQ3E5Z7JM2NTFQ5YJ8P9R4", - "data": { - "item": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "item_type": "action", - "incident_id": "6a5f1e28807515413b384bce", - "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", - "description": "CPU saturation started right after the v2.14 rollout; roll back and watch the error rate.", - "status": "in_progress", - "priority": "high", - "source_kind": "native", - "version": 2, - "assignee_ids": [ - 3790925372131 - ], - "assignees": [ - { - "type": "person", - "id": 3790925372131 - } - ], - "created_by": 3790925372131, - "updated_by": 3790925372131, - "created_at_seconds": 1785496400, - "updated_at_seconds": 1785496700 - } - } - } + "example": "responder_id,responder_name,total_incident_cnt,total_incidents_acknowledged\n3790925372131,alice,5,4\n" } } }, @@ -46733,32 +49166,37 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateWorkItemRequest" + "$ref": "#/components/schemas/InsightQueryRequest" }, "example": { - "work_item_id": "wi_9fK2mNqRtVwXyZaBcDeFgH", - "version": 1, - "title": "Roll back the v2.14 deployment on web-server-01 and web-server-02", - "status": "in_progress" + "start_time": 1712000000, + "end_time": 1712604800, + "responder_ids": [ + 3790925372131 + ], + "severities": [ + "Critical", + "Warning" + ] } } } } } }, - "/insight/account": { + "/insight/team": { "post": { - "operationId": "insightByAccount", - "summary": "Get account-level insight", - "description": "Return incident and alert metrics for the whole account, one row per time bucket.", + "operationId": "insightByTeam", + "summary": "Get team insight", + "description": "Return incident and alert metrics grouped by team, one row per team per time bucket.", "tags": [ "On-call/Analytics" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per time bucket for the whole account. `responder_ids` and `incident_ids` are ignored; use `/insight/responder` or `/insight/incident/list` for those.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- `total_alert_cnt`, `total_alert_event_cnt` and `noise_reduction_pct` honor only the time range, team, channel and severity filters; `query`, `labels`, `fields` and the duration filters apply to incident metrics only.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", - "href": "/en/api-reference/on-call/analytics/insight-by-account", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per team per time bucket. Incidents without a team are aggregated into a row that has no `team_id`. `responder_ids` and `incident_ids` are ignored.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- `total_alert_cnt`, `total_alert_event_cnt` and `noise_reduction_pct` honor only the time range, team, channel and severity filters; `query`, `labels`, `fields` and the duration filters apply to incident metrics only.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", + "href": "/en/api-reference/on-call/analytics/insight-by-team", "metadata": { - "sidebarTitle": "Get account-level insight" + "sidebarTitle": "Get team insight" } }, "responses": { @@ -46787,6 +49225,8 @@ "items": [ { "ts": 1740844800, + "team_id": 4295771902131, + "team_name": "SRE Team", "total_incident_cnt": 2, "total_incidents_acknowledged": 2, "total_incidents_closed": 2, @@ -46841,7 +49281,74 @@ "example": { "start_time": 1712000000, "end_time": 1712604800, - "aggregate_unit": "day", + "team_ids": [ + 4295771902131 + ], + "aggregate_unit": "day" + } + } + } + } + } + }, + "/insight/team/export": { + "post": { + "operationId": "insightTeamExport", + "summary": "Export team insight", + "description": "Export team insight metrics as a CSV file with the same rows as `/insight/team`.", + "tags": [ + "On-call/Analytics" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters as `/insight/team`. Rows without a team ID (incidents without a team) are skipped. The file has no time-bucket column, so with `aggregate_unit` the rows of different buckets cannot be told apart; export one bucket per request if you need the split.\n- `export_fields` sets the columns and their order: team_id, team_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_closed, total_incidents_auto_closed, total_incidents_manually_closed, total_incidents_timeout_closed, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_incidents_reassigned, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, mean_seconds_to_close, noise_reduction_pct, acknowledgement_pct, total_alert_cnt, total_alert_event_cnt, hours. Unknown or duplicate keys are rejected. When it is omitted, all columns are exported, and `hours` is included only when `split_hours` is true.\n- The incident-snapshot keys (progress, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, ackers, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, snooze_status, snoozed_before, ever_muted, frequency, is_rare, alert_cnt, active_alert_cnt, alert_event_cnt, description, labels, fields) are also accepted for compatibility and produce empty columns.\n- Column headers are localized (request locale, then the member's, then the account's). Time buckets follow `time_zone` (UTC when omitted).", + "href": "/en/api-reference/on-call/analytics/insight-team-export", + "metadata": { + "sidebarTitle": "Export team insight" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary", + "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''team_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." + }, + "example": "team_id,team_name,total_incident_cnt,total_incidents_closed\n4295771902131,SRE Team,12,10\n" + } + } + }, + "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/InsightQueryRequest" + }, + "example": { + "start_time": 1712000000, + "end_time": 1712604800, + "team_ids": [ + 4295771902131 + ], "severities": [ "Critical", "Warning" @@ -46852,19 +49359,19 @@ } } }, - "/insight/alert/topk-by-label": { + "/member/delete": { "post": { - "operationId": "insightTopkAlertsByLabel", - "summary": "Get top-K alerts grouped by check or resource", - "description": "Return the top-K alert groups aggregated either by `check` or by `resource` label over the specified time range.", + "operationId": "memberDelete", + "summary": "Delete member", + "description": "Remove a member from the organization by ID, email, phone, or name.", "tags": [ - "On-call/Analytics" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- Only the time range, `team_ids`, `channel_ids`, `severities`, `is_my_team` and `split_hours` filter the result; other filter fields and `aggregate_unit` are ignored.\n- Alerts are counted in hourly buckets, so the effective range is aligned to whole hours.\n- With `split_hours: true`, the top `k` is computed separately for each of `work`, `sleep` and `off`, so up to 3 × `k` rows come back.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.", - "href": "/en/api-reference/on-call/analytics/insight-topk-alerts-by-label", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Identify the member with one of the lookup fields; when several are sent, the first non-empty one wins in the order `member_id`, `member_name`, `email`, `phone`, `ref_id`.\n- Unless `is_force` is true, the call fails with `400 ReferenceExist` while the member belongs to a team, is a direct target of an escalation rule, or is in a schedule; `data.refs` lists each reference. A forced delete skips this check and leaves those references in place.\n- Deletion is soft: the member's status becomes `deleted`, any license seat the member holds is released, and the member's SSO identity links are removed. The member still resolves through `POST /person/infos`.\n- Members provisioned through SSO cannot be deleted while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/members/member-delete", "metadata": { - "sidebarTitle": "Get top-K alerts grouped by check or resource" + "sidebarTitle": "Delete member" } }, "responses": { @@ -46881,7 +49388,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/InsightAlertByLabelResponse" + "$ref": "#/components/schemas/MemberEmptyObject" } } } @@ -46889,25 +49396,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "label": "cpu-high", - "total_alert_cnt": 312, - "total_alert_event_cnt": 987 - }, - { - "label": "disk-full", - "total_alert_cnt": 178, - "total_alert_event_cnt": 452 - }, - { - "label": "memory-oom", - "total_alert_cnt": 94, - "total_alert_event_cnt": 231 - } - ] - } + "data": {} } } } @@ -46933,33 +49422,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightTopkAlertByLabelRequest" + "$ref": "#/components/schemas/MemberDeleteRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "label": "check", - "k": 10, - "orderby": "total_alert_cnt" + "member_id": 5068740052131 } } } } } }, - "/insight/channel": { + "/member/info": { "post": { - "operationId": "insightByChannel", - "summary": "Get channel insight", - "description": "Return incident and alert metrics grouped by channel, one row per channel per time bucket.", + "operationId": "memberInfo", + "summary": "Get current member info", + "description": "Return the profile and account context of the member who owns the credential.", "tags": [ - "On-call/Analytics" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per channel per time bucket. `responder_ids` and `incident_ids` are ignored.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- `total_alert_cnt`, `total_alert_event_cnt` and `noise_reduction_pct` honor only the time range, team, channel and severity filters; `query`, `labels`, `fields` and the duration filters apply to incident metrics only.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", - "href": "/en/api-reference/on-call/analytics/insight-by-channel", + "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 a member credential; calls made with the account owner's credentials return `400 BadRequest`. Use `POST /account/info` for the account owner.\n- `time_zone` is the member's own setting (empty string = follow the account), `account_time_zone` is the account's setting, and `resolved_time_zone` is the zone to render times in.", + "href": "/en/api-reference/platform/members/member-info", "metadata": { - "sidebarTitle": "Get channel insight" + "sidebarTitle": "Get current member info" } }, "responses": { @@ -46976,7 +49461,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/DimensionInsightResponse" + "$ref": "#/components/schemas/MemberInfoResponse" } } } @@ -46985,34 +49470,29 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [ - { - "ts": 1740844800, - "channel_id": 4321322010131, - "channel_name": "Production Alerts", - "total_incident_cnt": 2, - "total_incidents_acknowledged": 2, - "total_incidents_closed": 2, - "total_incidents_auto_closed": 0, - "total_incidents_manually_closed": 2, - "total_incidents_timeout_closed": 0, - "total_incidents_escalated": 0, - "total_incidents_manually_escalated": 0, - "total_incidents_timeout_escalated": 0, - "total_incidents_reassigned": 2, - "total_interruptions": 3, - "total_notifications": 6, - "total_engaged_seconds": 3317709, - "total_seconds_to_ack": 3317709, - "total_seconds_to_close": 3749514, - "mean_seconds_to_ack": 1658854.5, - "mean_seconds_to_close": 1874757, - "noise_reduction_pct": 0, - "acknowledgement_pct": 100, - "total_alert_cnt": 0, - "total_alert_event_cnt": 0 - } - ] + "account_avatar": "", + "account_email": "alice@example.com", + "account_id": 2451002751131, + "account_locale": "en-US", + "account_name": "Acme Corp", + "account_role_ids": [ + 6 + ], + "account_time_zone": "Asia/Shanghai", + "avatar": "/image/avatar1.png", + "country_code": "CN", + "created_at": 1701399971, + "domain": "acme", + "email": "alice@example.com", + "email_verified": true, + "is_external": false, + "locale": "zh-CN", + "member_id": 2476444212131, + "member_name": "Alice", + "phone": "+86185****0300", + "phone_verified": true, + "time_zone": "Asia/Shanghai", + "resolved_time_zone": "Asia/Shanghai" } } } @@ -47039,47 +49519,142 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightQueryRequest" + "$ref": "#/components/schemas/MemberInfoRequest" + }, + "example": {} + } + } + } + } + }, + "/member/info/reset": { + "post": { + "operationId": "memberResetInfo", + "summary": "Reset member info", + "description": "Identify a member and reset the specified profile fields.", + "tags": [ + "Platform/Members" + ], + "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- Identify the member with one of `member_id`, `member_name`, `email`, `phone`, or `ref_id`. If multiple identifiers are present, the server checks them in that order.\n- The caller must be the account owner, the member themself, or hold the Admin role; otherwise the call returns `403 AccessDenied`.\n- Put the fields to write under `updates`: `member_name`, `password`, `phone`, `country_code`, `email`, `avatar`, `locale`, `time_zone`, or `ref_id`. Omitted or `null` fields keep their current value; `updates` must carry at least one field.\n- A new `member_name`, `email`, or `phone` must not belong to another member of the account; a conflict returns `400`. A changed `email` or `phone` is marked unverified unless `from` is `api` and the account has member invitations disabled.\n- `updates.time_zone` set to an empty string clears the member's own time zone, so the member follows the account's.\n- `updates.country_code` is an ISO 3166-1 alpha-2 region code (e.g. \"CN\", \"US\"). It is an independently updatable field: `updates.phone` is not required, and the new region is stored even when the phone is unchanged. An explicit empty string is rejected with a 400.\n- When `updates.phone` has no \"+\" prefix, it is parsed with `updates.country_code` as the region hint, falling back to the member's stored region and then to \"CN\". Legacy digit calling codes such as \"86\" remain accepted only as parsing hints — stored values are always ISO region codes.\n- The top-level `country_code` is only a parsing hint for the identifying `phone`; it is never stored.\n- Fields are written one at a time; if a later field fails validation, the fields written before it in the same call stay saved.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable.\n- Concurrent profile updates or invitations in the same account can return `429 RequestTooFrequently`; retry after a moment.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/members/member-reset-info", + "metadata": { + "sidebarTitle": "Reset member info" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/MemberEmptyObject" + } + } + } + ] + }, + "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/MemberResetInfoRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "channel_ids": [ - 4321322010131 - ], - "aggregate_unit": "day" + "member_id": 2476444212131, + "updates": { + "member_name": "Alice Chen", + "locale": "zh-CN", + "time_zone": "Asia/Shanghai" + } } } } } } }, - "/insight/channel/export": { + "/member/invite": { "post": { - "operationId": "insightChannelExport", - "summary": "Export channel insight", - "description": "Export channel insight metrics as a CSV file with the same rows as `/insight/channel`.", + "operationId": "memberInvite", + "summary": "Invite members", + "description": "Batch invite new members to the organization by email or phone.", "tags": [ - "On-call/Analytics" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters as `/insight/channel`. Rows without a channel ID are skipped. The file has no time-bucket column, so with `aggregate_unit` the rows of different buckets cannot be told apart; export one bucket per request if you need the split.\n- `export_fields` sets the columns and their order: channel_id, channel_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_closed, total_incidents_auto_closed, total_incidents_manually_closed, total_incidents_timeout_closed, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_incidents_reassigned, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, mean_seconds_to_close, noise_reduction_pct, acknowledgement_pct, total_alert_cnt, total_alert_event_cnt, hours. Unknown or duplicate keys are rejected. When it is omitted, all columns are exported, and `hours` is included only when `split_hours` is true.\n- The incident-snapshot keys (progress, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, ackers, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, snooze_status, snoozed_before, ever_muted, frequency, is_rare, alert_cnt, active_alert_cnt, alert_event_cnt, description, labels, fields) are also accepted for compatibility and produce empty columns.\n- Column headers are localized (request locale, then the member's, then the account's). Time buckets follow `time_zone` (UTC when omitted).", - "href": "/en/api-reference/on-call/analytics/insight-channel-export", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Each entry needs `email`, or `member_name` together with `phone`.\n- Entries whose email or phone already belongs to a member of the account are skipped silently; `items` lists only the members created by this call and is `null` when none were created.\n- New members are created in `pending` status and are sent an invitation by email or SMS.\n- Emails are stored in lower case. If the account restricts member email domains, an address outside the allowlist returns `400`; duplicate emails or phones within one request also return `400`.\n- `country_code` must be an ISO 3166-1 alpha-2 region code (e.g. \"CN\"). It is validated and normalized to upper case before storage; invalid values are rejected with a 400.\n- When a member's `phone` has no \"+\" prefix, it is parsed with that member's `country_code` as the region hint (defaults to \"CN\" when omitted).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/members/member-invite", "metadata": { - "sidebarTitle": "Export channel insight" + "sidebarTitle": "Invite members" } }, "responses": { "200": { "description": "Success", "content": { - "application/octet-stream": { + "application/json": { "schema": { - "type": "string", - "format": "binary", - "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''channel_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/MemberInviteResponse" + } + } + } + ] }, - "example": "channel_id,channel_name,total_incident_cnt,total_incidents_closed\n4321322010131,Production Alerts,12,10\n" + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "member_id": 5068740052131, + "member_name": "Charlie" + }, + { + "member_id": 5068740052132, + "member_name": "Dave" + } + ] + } + } } } }, @@ -47104,17 +49679,26 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightQueryRequest" + "$ref": "#/components/schemas/MemberInviteRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "channel_ids": [ - 4321322010131 - ], - "severities": [ - "Critical", - "Warning" + "members": [ + { + "member_name": "Charlie", + "email": "charlie@example.com", + "locale": "en-US", + "time_zone": "Asia/Shanghai", + "role_ids": [ + 6 + ] + }, + { + "member_name": "Dave", + "phone": "13800138000", + "country_code": "CN", + "locale": "zh-CN", + "time_zone": "Asia/Shanghai" + } ] } } @@ -47122,32 +49706,90 @@ } } }, - "/insight/incident/export": { + "/member/list": { "post": { - "operationId": "insightIncidentExport", - "summary": "Export insight incidents", - "description": "Export the incidents matched by the analytics filters as a CSV file, one row per incident.", + "operationId": "memberList", + "summary": "List members", + "description": "Return a paginated list of organization members.", "tags": [ - "On-call/Analytics" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters and sort order as `/insight/incident/list`. Export stops once more than 100,000 rows have been written.\n- `start_time` is moved forward to the earliest date kept by the account's data retention; a range that ends before that date is rejected.\n- `export_fields` sets the columns and their order: incident_id, title, severity, progress, channel_id, channel_name, team_id, team_name, created_at, alert_cnt, active_alert_cnt, alert_event_cnt, seconds_to_ack, seconds_to_close, closed_by, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, engaged_seconds, hours, notifications, interruptions, acknowledgements, ackers, assignments, reassignments, escalations, manual_escalations, timeout_escalations, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, snooze_status, snoozed_before, ever_muted, frequency, is_rare, description, labels, fields. Unknown or duplicate keys are rejected; when omitted, every column except the aliases `owner_id`, `creator_id`, `closer_id`, `snoozed_before` and `is_rare` is exported.\n- `description_html_to_text: true` strips HTML from the `description` column.\n- Headers and formatted values use the request locale, then the member's, then the account's. Times are rendered in `time_zone`, falling back to the account time zone and then `Asia/Shanghai`.", - "href": "/en/api-reference/on-call/analytics/insight-incident-export", + "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- Returns members in `enabled` or `pending` status. Removed members and the account owner are not listed; resolve their IDs with `POST /person/infos`.\n- `role_id` returns the members holding that role; `member_id` returns at most that one member.", + "href": "/en/api-reference/platform/members/member-list", "metadata": { - "sidebarTitle": "Export insight incidents" + "sidebarTitle": "List members" } }, "responses": { "200": { "description": "Success", "content": { - "application/octet-stream": { + "application/json": { "schema": { - "type": "string", - "format": "binary", - "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''incident_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/MemberListResponse" + } + } + } + ] }, - "example": "incident_id,title,severity,created_at\n6a86b5d6f72de50ae1ce2ffb,CPU usage above 90%,Critical,2026-01-01 10:00:00 +0800 CST\n" + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "p": 1, + "limit": 5, + "total": 148, + "items": [ + { + "account_id": 2451002751131, + "member_id": 5068740052131, + "member_name": "Bob", + "country_code": "", + "phone": "+86151****6519", + "email": "bob@example.com", + "phone_verified": true, + "email_verified": true, + "avatar": "", + "status": "enabled", + "account_role_ids": [ + 2, + 6 + ], + "created_at": 1752030749, + "updated_at": 1775962064, + "ref_id": "", + "is_external": false + }, + { + "account_id": 2451002751131, + "member_id": 2476444212131, + "member_name": "Alice", + "country_code": "CN", + "phone": "+86185****0300", + "email": "alice@example.com", + "phone_verified": true, + "email_verified": true, + "avatar": "/image/avatar1.png", + "status": "enabled", + "account_role_ids": [ + 6 + ], + "created_at": 1701399971, + "updated_at": 1775809507, + "ref_id": "", + "is_external": false + } + ] + } + } } } }, @@ -47172,42 +49814,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightIncidentExportRequest" + "$ref": "#/components/schemas/MemberListRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "severities": [ - "Critical", - "Warning" - ], - "export_fields": [ - "incident_id", - "title", - "severity", - "created_at", - "seconds_to_close" - ], - "description_html_to_text": true + "p": 1, + "limit": 5 } } } } } }, - "/insight/incident/list": { + "/member/role/grant": { "post": { - "operationId": "insightIncidentList", - "summary": "List insight incidents", - "description": "Return a paged list of incidents with per-incident handling metrics used by the analytics dashboard.", + "operationId": "memberGrantRole", + "summary": "Grant role to member", + "description": "Add one or more roles to a member's existing role assignments.", "tags": [ - "On-call/Analytics" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- Sorted by incident creation time, newest first by default (`asc: true` for oldest first).\n- Page with `p` + `limit` (at most 10,000 records reachable) or, for deeper reads, pass the previous page's `search_after_ctx` back. When `search_after_ctx` is sent, `total` counts only the incidents after the cursor.\n- `responder_ids` keeps incidents in which any of the given members was a responder.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", - "href": "/en/api-reference/on-call/analytics/insight-incident-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Role IDs that do not exist are ignored; if none of them exist, the call succeeds without changes.\n- Roles the member already holds are kept once; no duplicates are added.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/members/member-grant-role", "metadata": { - "sidebarTitle": "List insight incidents" + "sidebarTitle": "Grant role to member" } }, "responses": { @@ -47224,7 +49854,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/InsightIncidentListResponse" + "$ref": "#/components/schemas/MemberEmptyObject" } } } @@ -47232,62 +49862,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "total": 2363, - "has_next_page": true, - "search_after_ctx": "6a86b5d6f72de50ae1ce2ffb", - "items": [ - { - "incident_id": "6a86b5d6f72de50ae1ce2ffb", - "title": "CPU usage above 90% on prod-web-01", - "description": "CPU usage stayed above the threshold for 5 minutes", - "team_id": 2477033058131, - "team_name": "SRE Team", - "channel_id": 3047621227131, - "channel_name": "Production Alerts", - "progress": "Closed", - "severity": "Critical", - "created_at": 1787213270, - "alert_cnt": 3, - "active_alert_cnt": 0, - "alert_event_cnt": 5, - "closed_by": "manually", - "creator_id": 2477273692131, - "creator_name": "alice", - "closer_id": 2477273692131, - "closer_name": "alice", - "seconds_to_ack": 14, - "seconds_to_close": 1830, - "engaged_seconds": 1816, - "hours": "work", - "responders": [ - { - "person_id": 2477273692131, - "assigned_at": 1787213270, - "acknowledged_at": 1787213284, - "person_name": "alice", - "email": "alice@example.com" - } - ], - "assigned_to": { - "escalate_rule_id": "66138789904a9027583dbc4e", - "layer_idx": 0, - "type": "assign", - "assigned_at": 1787213270, - "id": "b8tyUoRvCv4wsPndFRpmNL", - "escalate_rule_name": "On-call Policy" - }, - "notifications": 2, - "interruptions": 1, - "assignments": 1, - "reassignments": 0, - "acknowledgements": 1, - "escalations": 0, - "timeout_escalations": 0, - "manual_escalations": 0 - } - ] - } + "data": {} } } } @@ -47313,15 +49888,12 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightIncidentListRequest" + "$ref": "#/components/schemas/MemberRoleGrantRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "p": 1, - "limit": 20, - "severities": [ - "Critical" + "member_id": 5068740052131, + "role_ids": [ + 6 ] } } @@ -47329,19 +49901,19 @@ } } }, - "/insight/responder": { + "/member/role/revoke": { "post": { - "operationId": "insightByResponder", - "summary": "Get responder insight", - "description": "Return per-responder incident handling metrics, one row per responder per time bucket.", + "operationId": "memberRevokeRole", + "summary": "Revoke role from member", + "description": "Remove one or more roles from a member's role assignments.", "tags": [ - "On-call/Analytics" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per responder per time bucket; `responder_ids` limits which responders are returned. `seconds_to_close_from`/`seconds_to_close_to` and `incident_ids` are ignored.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", - "href": "/en/api-reference/on-call/analytics/insight-by-responder", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Role IDs that do not exist are ignored; if none of them exist, the call succeeds without changes.\n- Revoking every role leaves the member with no roles; it does not fall back to Viewer.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/members/member-revoke-role", "metadata": { - "sidebarTitle": "Get responder insight" + "sidebarTitle": "Revoke role from member" } }, "responses": { @@ -47358,7 +49930,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ResponderInsightResponse" + "$ref": "#/components/schemas/MemberEmptyObject" } } } @@ -47366,27 +49938,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "ts": 1740844800, - "responder_id": 3790925372131, - "responder_name": "alice", - "total_incident_cnt": 1, - "total_incidents_acknowledged": 1, - "total_incidents_reassigned": 0, - "total_incidents_escalated": 0, - "total_incidents_timeout_escalated": 0, - "total_incidents_manually_escalated": 0, - "total_interruptions": 1, - "total_notifications": 2, - "total_engaged_seconds": 10, - "total_seconds_to_ack": 2265624, - "mean_seconds_to_ack": 2265624, - "acknowledgement_pct": 100 - } - ] - } + "data": {} } } } @@ -47412,47 +49964,58 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightQueryRequest" + "$ref": "#/components/schemas/MemberRoleRevokeRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "responder_ids": [ - 3790925372131 - ], - "aggregate_unit": "day" + "member_id": 5068740052131, + "role_ids": [ + 6 + ] } } } } } }, - "/insight/responder/export": { + "/member/role/update": { "post": { - "operationId": "insightResponderExport", - "summary": "Export responder insight", - "description": "Export responder insight metrics as a CSV file with the same rows as `/insight/responder`.", + "operationId": "memberUpdateRole", + "summary": "Update member roles", + "description": "Replace a member's role assignments with the given set of roles.", "tags": [ - "On-call/Analytics" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters as `/insight/responder`. Rows without a responder ID are skipped. The file has no time-bucket column, so with `aggregate_unit` the rows of different buckets cannot be told apart; export one bucket per request if you need the split.\n- `export_fields` sets the columns and their order: responder_id, responder_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_reassigned, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, acknowledgement_pct, hours. Unknown or duplicate keys are rejected. When it is omitted, all columns are exported, and `hours` is included only when `split_hours` is true.\n- The incident-snapshot keys (progress, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, ackers, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, snooze_status, snoozed_before, ever_muted, frequency, is_rare, alert_cnt, active_alert_cnt, alert_event_cnt, description, labels, fields) are also accepted for compatibility and produce empty columns.\n- Column headers are localized (request locale, then the member's, then the account's). Time buckets follow `time_zone` (UTC when omitted).", - "href": "/en/api-reference/on-call/analytics/insight-responder-export", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- An empty or omitted `role_ids` assigns the built-in Viewer role (`8`).\n- Role IDs that do not exist are dropped; if none of the given IDs exist, the member ends up with no roles.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/members/member-update-role", "metadata": { - "sidebarTitle": "Export responder insight" + "sidebarTitle": "Update member roles" } }, "responses": { "200": { "description": "Success", "content": { - "application/octet-stream": { + "application/json": { "schema": { - "type": "string", - "format": "binary", - "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''responder_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/MemberEmptyObject" + } + } + } + ] }, - "example": "responder_id,responder_name,total_incident_cnt,total_incidents_acknowledged\n3790925372131,alice,5,4\n" + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} + } } } }, @@ -47477,17 +50040,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightQueryRequest" + "$ref": "#/components/schemas/MemberRoleUpdateRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "responder_ids": [ - 3790925372131 - ], - "severities": [ - "Critical", - "Warning" + "member_id": 5068740052131, + "role_ids": [ + 2, + 6 ] } } @@ -47495,19 +50054,19 @@ } } }, - "/insight/team": { + "/monit/datasource/create": { "post": { - "operationId": "insightByTeam", - "summary": "Get team insight", - "description": "Return incident and alert metrics grouped by team, one row per team per time bucket.", + "operationId": "monit-datasource-write-create", + "summary": "Create datasource", + "description": "Create a monitoring datasource of one of 15 supported types and bind it to a Monitors edge cluster.", "tags": [ - "On-call/Analytics" + "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- One row per team per time bucket. Incidents without a team are aggregated into a row that has no `team_id`. `responder_ids` and `incident_ids` are ignored.\n- Incidents are counted by creation time. Rows are sorted by `ts` from newest to oldest, and a bucket (or dimension value) with no incidents produces no row — missing rows mean zero. `split_hours: true` returns up to three rows per bucket, one per `hours` value.\n- `total_alert_cnt`, `total_alert_event_cnt` and `noise_reduction_pct` honor only the time range, team, channel and severity filters; `query`, `labels`, `fields` and the duration filters apply to incident metrics only.\n- Members who are neither the account owner nor an admin only get data from channels they can access; other channels are silently excluded.\n- With `is_my_team: true`, `team_ids` is narrowed to the caller's teams. If none of the sent `team_ids` is one of the caller's teams, or the caller belongs to no team, the result is empty.", - "href": "/en/api-reference/on-call/analytics/insight-by-team", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- `type_ident` must be one of: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`. The last five (`redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`) are diagnostic-only: they cannot evaluate alerts, so `alerting_enabled` must not be `true`.\n- `name` must be unique within the account across all types; a duplicate fails with `InvalidParameter`.\n- `edge_cluster_name` must be an existing Monitors edge cluster of the account; that cluster evaluates rules and runs queries for the datasource.\n- Put the type-specific settings in `payload.`. For `elasticsearch`, `payload.elasticsearch.deployment` is required (`cloud` or `self-managed`). `tencent_cls` requires every edge instance in the cluster to run Monitors edge v0.66.0 or later.\n- Omitted `enabled` defaults to `true`; omitted `alerting_enabled` defaults to `true` for alerting types and `false` for diagnostic-only types. Explicit `null` for either is rejected.\n- `manage_team_id` and `readonly_team_ids` restrict who can manage or query the datasource; omit both to leave it open to every member.\n- Responses return credentials of non-diagnostic types (for example Prometheus Basic Auth passwords) as stored. Diagnostic passwords and Kafka private keys are returned only when they are `${env:NAME}` references. Treat responses as sensitive.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-create", "metadata": { - "sidebarTitle": "Get team insight" + "sidebarTitle": "Create datasource" } }, "responses": { @@ -47524,7 +50083,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/DimensionInsightResponse" + "$ref": "#/components/schemas/DataSourceItem" } } } @@ -47533,34 +50092,27 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [ - { - "ts": 1740844800, - "team_id": 4295771902131, - "team_name": "SRE Team", - "total_incident_cnt": 2, - "total_incidents_acknowledged": 2, - "total_incidents_closed": 2, - "total_incidents_auto_closed": 0, - "total_incidents_manually_closed": 2, - "total_incidents_timeout_closed": 0, - "total_incidents_escalated": 0, - "total_incidents_manually_escalated": 0, - "total_incidents_timeout_escalated": 0, - "total_incidents_reassigned": 2, - "total_interruptions": 3, - "total_notifications": 6, - "total_engaged_seconds": 3317709, - "total_seconds_to_ack": 3317709, - "total_seconds_to_close": 3749514, - "mean_seconds_to_ack": 1658854.5, - "mean_seconds_to_close": 1874757, - "noise_reduction_pct": 0, - "acknowledgement_pct": 100, - "total_alert_cnt": 0, - "total_alert_event_cnt": 0 + "id": 10, + "account_id": 10023, + "type_ident": "prometheus", + "name": "Prometheus Prod", + "enabled": true, + "note": "Production Prometheus", + "address": "http://prometheus.example.com:9090", + "payload": { + "prometheus": { + "basic_auth_enabled": false, + "basic_auth_username": "", + "basic_auth_password": "", + "tls_skip_verify": false } - ] + }, + "edge_cluster_name": "default", + "updated_at": 1712000000, + "alerting_enabled": true, + "manage_team_id": null, + "readonly_team_ids": null, + "creator_id": 20001 } } } @@ -47587,47 +50139,64 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightQueryRequest" + "$ref": "#/components/schemas/DataSourceUpsertRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "team_ids": [ - 4295771902131 - ], - "aggregate_unit": "day" + "type_ident": "prometheus", + "name": "Prometheus Prod", + "note": "Production Prometheus", + "address": "http://prometheus.example.com:9090", + "edge_cluster_name": "default", + "payload": { + "prometheus": { + "basic_auth_enabled": false + } + } } } } } } }, - "/insight/team/export": { + "/monit/datasource/delete": { "post": { - "operationId": "insightTeamExport", - "summary": "Export team insight", - "description": "Export team insight metrics as a CSV file with the same rows as `/insight/team`.", + "operationId": "monit-datasource-write-delete", + "summary": "Delete datasource", + "description": "Delete a datasource by ID; alert rules that reference it are not blocked.", "tags": [ - "On-call/Analytics" + "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/day**; **20 requests/minute**; **10 requests/second** per account |\n| Permissions | **Analytics Read** (`on-call`) |\n\n## Usage\n\n- The response is a CSV file (`Content-Type: application/octet-stream`), not a JSON envelope. Validation errors are returned as JSON before any CSV bytes are written.\n- Takes the same filters as `/insight/team`. Rows without a team ID (incidents without a team) are skipped. The file has no time-bucket column, so with `aggregate_unit` the rows of different buckets cannot be told apart; export one bucket per request if you need the split.\n- `export_fields` sets the columns and their order: team_id, team_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_closed, total_incidents_auto_closed, total_incidents_manually_closed, total_incidents_timeout_closed, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_incidents_reassigned, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, mean_seconds_to_close, noise_reduction_pct, acknowledgement_pct, total_alert_cnt, total_alert_event_cnt, hours. Unknown or duplicate keys are rejected. When it is omitted, all columns are exported, and `hours` is included only when `split_hours` is true.\n- The incident-snapshot keys (progress, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, ackers, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, snooze_status, snoozed_before, ever_muted, frequency, is_rare, alert_cnt, active_alert_cnt, alert_event_cnt, description, labels, fields) are also accepted for compatibility and produce empty columns.\n- Column headers are localized (request locale, then the member's, then the account's). Time buckets follow `time_zone` (UTC when omitted).", - "href": "/en/api-reference/on-call/analytics/insight-team-export", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- Alert rules that reference the datasource are not blocked or edited; their open alerts on it are closed automatically.\n- Deleting an ID that does not exist succeeds as a no-op; an ID in another account returns `ResourceNotFound`.\n- Only the account owner, Admin members, the creator and members of the managing team can delete a datasource (anyone with the permission when no managing team is set); others get `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-delete", "metadata": { - "sidebarTitle": "Export team insight" + "sidebarTitle": "Delete datasource" } }, "responses": { "200": { "description": "Success", "content": { - "application/octet-stream": { + "application/json": { "schema": { - "type": "string", - "format": "binary", - "description": "CSV file (`Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename*=UTF-8''team_export_yyyyMMdd_HHmmss.csv`). The first row holds localized column headers." + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + ] }, - "example": "team_id,team_name,total_incident_cnt,total_incidents_closed\n4295771902131,SRE Team,12,10\n" + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} + } } } }, @@ -47652,37 +50221,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/InsightQueryRequest" + "$ref": "#/components/schemas/IDRequest" }, "example": { - "start_time": 1712000000, - "end_time": 1712604800, - "team_ids": [ - 4295771902131 - ], - "severities": [ - "Critical", - "Warning" - ] + "id": 10 } } } } } }, - "/member/delete": { + "/monit/datasource/info": { "post": { - "operationId": "memberDelete", - "summary": "Delete member", - "description": "Remove a member from the organization by ID, email, phone, or name.", + "operationId": "monit-datasource-read-info", + "summary": "Get datasource detail", + "description": "Return one datasource by ID, including its full `payload` configuration.", "tags": [ - "Platform/Members" + "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Identify the member with one of the lookup fields; when several are sent, the first non-empty one wins in the order `member_id`, `member_name`, `email`, `phone`, `ref_id`.\n- Unless `is_force` is true, the call fails with `400 ReferenceExist` while the member belongs to a team, is a direct target of an escalation rule, or is in a schedule; `data.refs` lists each reference. A forced delete skips this check and leaves those references in place.\n- Deletion is soft: the member's status becomes `deleted`, any license seat the member holds is released, and the member's SSO identity links are removed. The member still resolves through `POST /person/infos`.\n- Members provisioned through SSO cannot be deleted while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/members/member-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- Requires manage access to the datasource (see `manage_team_id`); members who can only query it get `AccessDenied`. Use `/monit/datasource/list` for the datasources you can query.\n- The response is sensitive: `payload` holds connection settings, and credentials of non-diagnostic types are returned as stored. Diagnostic passwords and Kafka private keys are returned only when they are `${env:NAME}` references; `tencent_cls` `secret_key` is returned as an empty string unless it is a `${env:NAME}` reference.\n- An unknown ID, or one in another account, returns `ResourceNotFound`.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-info", "metadata": { - "sidebarTitle": "Delete member" + "sidebarTitle": "Get datasource detail" } }, "responses": { @@ -47699,7 +50260,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/MemberEmptyObject" + "$ref": "#/components/schemas/DataSourceItem" } } } @@ -47707,7 +50268,29 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "id": 10, + "account_id": 10023, + "type_ident": "prometheus", + "name": "Prometheus Prod", + "enabled": true, + "note": "Production Prometheus", + "address": "http://prometheus.example.com:9090", + "payload": { + "prometheus": { + "basic_auth_enabled": false, + "basic_auth_username": "", + "basic_auth_password": "", + "tls_skip_verify": false + } + }, + "edge_cluster_name": "default", + "updated_at": 1712000000, + "alerting_enabled": true, + "manage_team_id": null, + "readonly_team_ids": null, + "creator_id": 20001 + } } } } @@ -47733,29 +50316,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemberDeleteRequest" + "$ref": "#/components/schemas/IDRequest" }, "example": { - "member_id": 5068740052131 + "id": 10 } } } } } }, - "/member/info": { + "/monit/datasource/list": { "post": { - "operationId": "memberInfo", - "summary": "Get current member info", - "description": "Return the profile and account context of the member who owns the credential.", + "operationId": "monit-datasource-read-list", + "summary": "List datasources", + "description": "List the account's datasources that the caller can query, optionally filtered by type or exact name.", "tags": [ - "Platform/Members" + "Monitors/Data sources" ], "x-mint": { - "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 a member credential; calls made with the account owner's credentials return `400 BadRequest`. Use `POST /account/info` for the account owner.\n- `time_zone` is the member's own setting (empty string = follow the account), `account_time_zone` is the account's setting, and `resolved_time_zone` is the zone to render times in.", - "href": "/en/api-reference/platform/members/member-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- Omit `type` and `name` to return every datasource you can query; `type` and `name` are exact-match filters. An unrecognized `type` returns an empty array. The result is not paginated.\n- Only datasources the caller can query are returned (see `readonly_team_ids`); each item carries `my_perm` (`manage` or `readonly`).\n- `payload` is always `null` in list items. Use `/monit/datasource/info` to read the configuration of a datasource you can manage.\n- `address` in list items has userinfo (`user:password@`), the query string and the fragment removed from each comma-separated entry. `/monit/datasource/info` returns the address as stored.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-list", "metadata": { - "sidebarTitle": "Get current member info" + "sidebarTitle": "List datasources" } }, "responses": { @@ -47772,7 +50355,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/MemberInfoResponse" + "$ref": "#/components/schemas/DataSourceListResponse" } } } @@ -47780,31 +50363,25 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "account_avatar": "", - "account_email": "alice@example.com", - "account_id": 2451002751131, - "account_locale": "en-US", - "account_name": "Acme Corp", - "account_role_ids": [ - 6 - ], - "account_time_zone": "Asia/Shanghai", - "avatar": "/image/avatar1.png", - "country_code": "CN", - "created_at": 1701399971, - "domain": "acme", - "email": "alice@example.com", - "email_verified": true, - "is_external": false, - "locale": "zh-CN", - "member_id": 2476444212131, - "member_name": "Alice", - "phone": "+86185****0300", - "phone_verified": true, - "time_zone": "Asia/Shanghai", - "resolved_time_zone": "Asia/Shanghai" - } + "data": [ + { + "id": 10, + "account_id": 10023, + "type_ident": "prometheus", + "name": "Prometheus Prod", + "enabled": true, + "note": "Production Prometheus", + "address": "http://prometheus.example.com:9090", + "payload": null, + "edge_cluster_name": "default", + "updated_at": 1712000000, + "alerting_enabled": true, + "manage_team_id": null, + "readonly_team_ids": null, + "creator_id": 20001, + "my_perm": "manage" + } + ] } } } @@ -47830,27 +50407,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemberInfoRequest" + "$ref": "#/components/schemas/DataSourceListRequest" }, - "example": {} + "example": { + "type": "prometheus" + } } } } } }, - "/member/info/reset": { + "/monit/datasource/sls/logstores": { "post": { - "operationId": "memberResetInfo", - "summary": "Reset member info", - "description": "Identify a member and reset the specified profile fields.", + "operationId": "monit-datasource-read-sls-logstores", + "summary": "List SLS logstores", + "description": "List logstores within an SLS project for the specified SLS datasource.", "tags": [ - "Platform/Members" + "Monitors/Data sources" ], "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- Identify the member with one of `member_id`, `member_name`, `email`, `phone`, or `ref_id`. If multiple identifiers are present, the server checks them in that order.\n- The caller must be the account owner, the member themself, or hold the Admin role; otherwise the call returns `403 AccessDenied`.\n- Put the fields to write under `updates`: `member_name`, `password`, `phone`, `country_code`, `email`, `avatar`, `locale`, `time_zone`, or `ref_id`. Omitted or `null` fields keep their current value; `updates` must carry at least one field.\n- A new `member_name`, `email`, or `phone` must not belong to another member of the account; a conflict returns `400`. A changed `email` or `phone` is marked unverified unless `from` is `api` and the account has member invitations disabled.\n- `updates.time_zone` set to an empty string clears the member's own time zone, so the member follows the account's.\n- `updates.country_code` is an ISO 3166-1 alpha-2 region code (e.g. \"CN\", \"US\"). It is an independently updatable field: `updates.phone` is not required, and the new region is stored even when the phone is unchanged. An explicit empty string is rejected with a 400.\n- When `updates.phone` has no \"+\" prefix, it is parsed with `updates.country_code` as the region hint, falling back to the member's stored region and then to \"CN\". Legacy digit calling codes such as \"86\" remain accepted only as parsing hints — stored values are always ISO region codes.\n- The top-level `country_code` is only a parsing hint for the identifying `phone`; it is never stored.\n- Fields are written one at a time; if a later field fails validation, the fields written before it in the same call stay saved.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable.\n- Concurrent profile updates or invitations in the same account can return `429 RequestTooFrequently`; retry after a moment.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/members/member-reset-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- The datasource identified by `id` must be of type `sls`; other types fail with `InvalidParameter`.\n- The caller needs query access to the datasource (see `readonly_team_ids` on the datasource); otherwise the call fails with 403 `AccessDenied`.\n- Supply `project` to select the SLS project whose logstores to list; use `offset` and `size` to paginate. The response is a plain array of logstore names.\n- The request is relayed to the Monitors edge cluster of the datasource, which calls Alibaba Cloud with the stored credentials; it times out after 30 seconds. Fails with `InvalidParameter` when no edge instance of that cluster is online, and with HTTP 503 `ServiceUnavailable` when the edge version does not support metadata discovery.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-sls-logstores", "metadata": { - "sidebarTitle": "Reset member info" + "sidebarTitle": "List SLS logstores" } }, "responses": { @@ -47867,7 +50446,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/MemberEmptyObject" + "$ref": "#/components/schemas/SLSLogstoresResponse" } } } @@ -47875,7 +50454,10 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": [ + "logstore-1", + "logstore-2" + ] } } } @@ -47901,34 +50483,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemberResetInfoRequest" + "$ref": "#/components/schemas/SLSLogstoresRequest" }, "example": { - "member_id": 2476444212131, - "updates": { - "member_name": "Alice Chen", - "locale": "zh-CN", - "time_zone": "Asia/Shanghai" - } + "id": 10, + "project": "project-a", + "offset": 0, + "size": 50 } } } } } }, - "/member/invite": { + "/monit/datasource/sls/projects": { "post": { - "operationId": "memberInvite", - "summary": "Invite members", - "description": "Batch invite new members to the organization by email or phone.", + "operationId": "monit-datasource-read-sls-projects", + "summary": "List SLS projects", + "description": "List Alibaba Cloud SLS (Simple Log Service) projects available in the specified SLS datasource.", "tags": [ - "Platform/Members" + "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Each entry needs `email`, or `member_name` together with `phone`.\n- Entries whose email or phone already belongs to a member of the account are skipped silently; `items` lists only the members created by this call and is `null` when none were created.\n- New members are created in `pending` status and are sent an invitation by email or SMS.\n- Emails are stored in lower case. If the account restricts member email domains, an address outside the allowlist returns `400`; duplicate emails or phones within one request also return `400`.\n- `country_code` must be an ISO 3166-1 alpha-2 region code (e.g. \"CN\"). It is validated and normalized to upper case before storage; invalid values are rejected with a 400.\n- When a member's `phone` has no \"+\" prefix, it is parsed with that member's `country_code` as the region hint (defaults to \"CN\" when omitted).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/members/member-invite", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- The datasource identified by `id` must be of type `sls`; other types fail with `InvalidParameter`.\n- The caller needs query access to the datasource (see `readonly_team_ids` on the datasource); otherwise the call fails with 403 `AccessDenied`.\n- Use `query` to filter the project list and `offset` and `size` to paginate; `count` is the number of projects in the page and `total` the number matching the filter.\n- The request is relayed to the Monitors edge cluster of the datasource, which calls Alibaba Cloud with the stored credentials; it times out after 30 seconds. Fails with `InvalidParameter` when no edge instance of that cluster is online, and with HTTP 503 `ServiceUnavailable` when the edge version does not support metadata discovery.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-sls-projects", "metadata": { - "sidebarTitle": "Invite members" + "sidebarTitle": "List SLS projects" } }, "responses": { @@ -47945,7 +50525,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/MemberInviteResponse" + "$ref": "#/components/schemas/SLSProjectsResponse" } } } @@ -47954,16 +50534,28 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [ + "projects": [ { - "member_id": 5068740052131, - "member_name": "Charlie" + "projectName": "project-a", + "description": "Production logs", + "status": "Normal", + "owner": "", + "region": "cn-shanghai", + "createTime": "1710000000", + "lastModifyTime": "1712000000" }, { - "member_id": 5068740052132, - "member_name": "Dave" + "projectName": "project-b", + "description": "Staging logs", + "status": "Normal", + "owner": "", + "region": "cn-shanghai", + "createTime": "1710000000", + "lastModifyTime": "1712000000" } - ] + ], + "count": 2, + "total": 2 } } } @@ -47990,51 +50582,57 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemberInviteRequest" + "$ref": "#/components/schemas/SLSProjectsRequest" }, "example": { - "members": [ - { - "member_name": "Charlie", - "email": "charlie@example.com", - "locale": "en-US", - "time_zone": "Asia/Shanghai", - "role_ids": [ - 6 - ] - }, - { - "member_name": "Dave", - "phone": "13800138000", - "country_code": "CN", - "locale": "zh-CN", - "time_zone": "Asia/Shanghai" - } - ] + "id": 10, + "query": "", + "offset": 0, + "size": 50 } } } } } }, - "/member/list": { + "/monit/datasource/tools/invoke": { "post": { - "operationId": "memberList", - "summary": "List members", - "description": "Return a paginated list of organization members.", - "tags": [ - "Platform/Members" - ], - "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- Returns members in `enabled` or `pending` status. Removed members and the account owner are not listed; resolve their IDs with `POST /person/infos`.\n- `role_id` returns the members holding that role; `member_id` returns at most that one member.", - "href": "/en/api-reference/platform/members/member-list", - "metadata": { - "sidebarTitle": "List members" - } + "description": "Execute one deterministic diagnostic or query tool against a configured datasource.", + "operationId": "monit-datasource-tools-invoke", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DatasourceToolInvokeRequest" + }, + "examples": { + "diagnostic": { + "value": { + "datasource_id": 10, + "params": {}, + "tool": "mysql.overview" + } + }, + "query": { + "value": { + "datasource_id": 24000, + "tool": "prometheus.query", + "params": { + "expr": "sum(rate(http_requests_total[5m]))", + "execution": { + "kind": "instant", + "to_ms": 1789000000000 + } + } + } + } + } + } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { "schema": { @@ -48043,112 +50641,188 @@ "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/MemberListResponse" + "$ref": "#/components/schemas/DatasourceToolResult" } - } + }, + "type": "object" } ] }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "p": 1, - "limit": 5, - "total": 148, - "items": [ - { - "account_id": 2451002751131, - "member_id": 5068740052131, - "member_name": "Bob", - "country_code": "", - "phone": "+86151****6519", - "email": "bob@example.com", - "phone_verified": true, - "email_verified": true, - "avatar": "", - "status": "enabled", - "account_role_ids": [ - 2, - 6 - ], - "created_at": 1752030749, - "updated_at": 1775962064, - "ref_id": "", - "is_external": false + "examples": { + "diagnostic": { + "value": { + "data": { + "data": { + "version": "8.0.36" + }, + "datasource_id": 10, + "summary": "MySQL overview", + "tool": "mysql.overview" }, - { - "account_id": 2451002751131, - "member_id": 2476444212131, - "member_name": "Alice", - "country_code": "CN", - "phone": "+86185****0300", - "email": "alice@example.com", - "phone_verified": true, - "email_verified": true, - "avatar": "/image/avatar1.png", - "status": "enabled", - "account_role_ids": [ - 6 - ], - "created_at": 1701399971, - "updated_at": 1775809507, - "ref_id": "", - "is_external": false + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + } + }, + "query": { + "value": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "datasource_id": 24000, + "tool": "prometheus.query", + "data": { + "format": "explore_result.v1", + "result": { + "kind": "samples", + "samples": [ + { + "labels": { + "__name__": "up", + "instance": "203.0.113.10:9090" + }, + "value": 1 + } + ] + } + } } - ] + } } } } - } + }, + "description": "Success" }, "400": { - "$ref": "#/components/responses/BadRequest" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: invalid_request, tool_not_supported, datasource_error." }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { - "$ref": "#/components/responses/Forbidden" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: access_denied." + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: datasource_not_found." + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: datasource_disabled, datasource_in_use." + }, + "413": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: source_too_large, result_too_large." }, "429": { - "$ref": "#/components/responses/TooManyRequests" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: overloaded." + }, + "499": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: canceled." }, "500": { - "$ref": "#/components/responses/ServerError" + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: internal." + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: no_active_edge, edge_upgrade_required, mixed_edge_versions." + }, + "504": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: timeout." } }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MemberListRequest" - }, - "example": { - "p": 1, - "limit": 5 - } - } + "summary": "Invoke datasource tool", + "tags": [ + "Monitors/Data sources" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **2,000 requests/minute**; **32 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\nUse datasource IDs from `/monit/datasource/list`. Disabled datasources return `datasource_disabled`; `alerting_enabled=false` does not block tools. Errors use non-2xx HTTP status and `error.code`, `error.message`, `error.reason`. `tool_not_supported` indicates the selected executor does not provide this tool; it is not a vendor permission error. Never retry through another Edge or the legacy diagnose endpoint automatically.\n\n## Usage\n\n- The caller needs query access to the datasource (see `readonly_team_ids` on the datasource); without it the call fails with 403 `access_denied`. A datasource in another account returns 404 `datasource_not_found`.\n- Diagnostic tools exist only for datasource types `mysql`, `postgres`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`, `elasticsearch`, `prometheus`, `loki` and `victorialogs`; `oracle`, `clickhouse`, `sls` and `tencent_cls` support only their `.query` tool. Other combinations fail with `invalid_request`.\n- Two tool families share this entry: diagnostic tools defined by the executing Edge (e.g. `mysql.overview`, `prometheus.metric_trends`) and query tools named `.query`. The tool prefix must match the datasource type.\n- Query tools require the Edge cluster to support Explore queries (protocol milestone v0.68.0); diagnostic tools require the v0.71.0 base invoke protocol. Unsupported clusters fail with `edge_upgrade_required`, `mixed_edge_versions`, or `edge_version_unknown`; never fall back to `/monit/query/data` or another endpoint automatically.\n- For query tools, `params` follows the per-datasource schema named in the `tool` field description. `expr` and `execution` are always required. `limit`/`direction` only bound raw-log retrieval, never SQL rows or scanned data. Unknown extension fields are tolerated but never executed or forwarded.\n- Query `data` is the complete Explore result: `format` is `explore_result.v1` and `result.kind` is `samples`, `frames`, or `logs`; log results keep `applied_limit` and `has_more`. Query results never synthesize `summary` or `truncated`.\n- Request body limit 128 KiB; complete success response limit 10 MiB for both families; diagnostic tool timeout at most 25 seconds.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-tools-invoke", + "metadata": { + "sidebarTitle": "Invoke datasource tool" } } } }, - "/member/role/grant": { + "/monit/datasource/update": { "post": { - "operationId": "memberGrantRole", - "summary": "Grant role to member", - "description": "Add one or more roles to a member's existing role assignments.", + "operationId": "monit-datasource-write-update", + "summary": "Update datasource", + "description": "Update a datasource by ID, replacing its name, note, address, payload and edge cluster.", "tags": [ - "Platform/Members" + "Monitors/Data sources" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Role IDs that do not exist are ignored; if none of them exist, the call succeeds without changes.\n- Roles the member already holds are kept once; no duplicates are added.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/members/member-grant-role", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- This is a full replace, not a patch: send `type_ident`, `name`, `edge_cluster_name`, `payload` and (except for Elasticsearch `cloud`) `address` on every call. `note`, `address` and `payload` overwrite the stored values, so an omitted `note` is cleared.\n- Omitting `enabled`, `alerting_enabled`, `manage_team_id` or `readonly_team_ids` keeps the current value. `null` for `enabled` or `alerting_enabled` is rejected; `null` for the two team fields clears them.\n- Secrets: for the diagnostic types, omit the password (and the Kafka `tls_key`) to keep the stored value or send an empty string to clear it. For `tencent_cls`, an omitted or empty `secret_key` keeps the stored key. Other types need their credentials resent.\n- Setting `enabled` or `alerting_enabled` to `false`, or changing `type_ident` or `edge_cluster_name`, closes open alerts of the rules that use this datasource. Renaming it closes open alerts of rules whose `ds_list` name pattern no longer matches the new name.\n- Turning `alerting_enabled` off fails with HTTP 409 `UndonedOrderExist` while an enabled alert rule still selects the datasource.\n- Only the account owner, Admin members, the creator and members of the managing team can update a datasource (anyone with the permission when no managing team is set); others get `AccessDenied`. An unknown ID, or one in another account, returns `ResourceNotFound`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-update", "metadata": { - "sidebarTitle": "Grant role to member" + "sidebarTitle": "Update datasource" } }, "responses": { @@ -48165,7 +50839,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/MemberEmptyObject" + "$ref": "#/components/schemas/DataSourceItem" } } } @@ -48173,7 +50847,29 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "id": 10, + "account_id": 10023, + "type_ident": "prometheus", + "name": "Prometheus Prod v2", + "enabled": true, + "note": "Updated", + "address": "http://prometheus-v2.example.com:9090", + "payload": { + "prometheus": { + "basic_auth_enabled": false, + "basic_auth_username": "", + "basic_auth_password": "", + "tls_skip_verify": false + } + }, + "edge_cluster_name": "default", + "updated_at": 1712100000, + "alerting_enabled": true, + "manage_team_id": null, + "readonly_team_ids": null, + "creator_id": 20001 + } } } } @@ -48199,63 +50895,78 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemberRoleGrantRequest" + "$ref": "#/components/schemas/DataSourceUpsertRequest" }, "example": { - "member_id": 5068740052131, - "role_ids": [ - 6 - ] + "id": 10, + "type_ident": "prometheus", + "name": "Prometheus Prod v2", + "note": "Updated", + "address": "http://prometheus-v2.example.com:9090", + "edge_cluster_name": "default", + "payload": { + "prometheus": { + "basic_auth_enabled": false + } + } } } } } } }, - "/member/role/revoke": { - "post": { - "operationId": "memberRevokeRole", - "summary": "Revoke role from member", - "description": "Remove one or more roles from a member's role assignments.", - "tags": [ - "Platform/Members" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- Role IDs that do not exist are ignored; if none of them exist, the call succeeds without changes.\n- Revoking every role leaves the member with no roles; it does not fall back to Viewer.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/members/member-revoke-role", - "metadata": { - "sidebarTitle": "Revoke role from member" + "/monit/prometheus/api/v1/label/{label_name}/values": { + "get": { + "description": "Read label values from a Prometheus-compatible data source through the Monitors proxy.", + "operationId": "monit-prometheus-read-label-values", + "parameters": [ + { + "name": "label_name", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Label name to enumerate values for, for example `job`." + }, + { + "name": "X-DSID", + "in": "header", + "required": false, + "schema": { + "type": "string" + }, + "description": "Data source ID to query, as a decimal string. Must reference a Prometheus data source owned by the authenticated account. When omitted, the request is served by the platform's own Prometheus instead of one of your data sources." } - }, + ], "responses": { "200": { - "description": "Success", + "description": "Native Prometheus label-values response returned by the data source.", "content": { "application/json": { "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/components/schemas/MemberEmptyObject" - } - } - } - ] + "$ref": "#/components/schemas/PrometheusLabelValuesResponse" }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "status": "success", + "data": [ + "api", + "db", + "worker" + ] } } } }, "400": { - "$ref": "#/components/responses/BadRequest" + "description": "The `X-DSID` header is not a number, the data source is not a Prometheus data source, no monit-edge is registered for the data source's cluster, or the data source does not exist or belongs to another account (message `data source not found`). Returned as `text/plain`.", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } }, "401": { "$ref": "#/components/responses/Unauthorized" @@ -48267,41 +50978,54 @@ "$ref": "#/components/responses/TooManyRequests" }, "500": { - "$ref": "#/components/responses/ServerError" + "description": "The data source lookup or proxied request failed. Returned as `text/plain`.", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + } } }, + "summary": "List Prometheus label values", + "tags": [ + "Monitors/Data sources" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n| Edge requirement | Querying a specific data source requires **monit-edge v0.35.0 or later** |\n\n## Usage\n\n- Pass the target data source ID in the `X-DSID` header. It must belong to the authenticated account and be a Prometheus data source; use `/monit/datasource/list` to obtain its ID.\n- When the data source restricts querying to certain teams, only members of those teams, its managing team, and account owners or admins can query it; others get 403. An unknown data source ID returns 400.\n- The 200 body is the data source's native Prometheus HTTP API payload, **not** the standard `{ request_id, data }` envelope. Query-string parameters are forwarded unchanged, so Prometheus's own parameters such as `match[]`, `start`, and `end` work.\n- When `X-DSID` is omitted, or any monit-edge of the data source's cluster is older than v0.35.0, the request is answered by the platform's own Prometheus instead of your data source. Send the header and keep monit-edge up to date to get your data source's values.\n- Failures raised before the data source is reached are returned as `text/plain` with the matching 4xx or 5xx status. A status of 400 or above returned by the data source itself is passed through with its own body.", + "href": "/en/api-reference/monitors/data-sources/monit-prometheus-read-label-values", + "metadata": { + "sidebarTitle": "List Prometheus label values" + } + } + } + }, + "/monit/query/explore": { + "post": { + "description": "Run an Explore query against a configured data source and return frames, samples, or logs.", + "operationId": "monit-read-query-explore", "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/MemberRoleRevokeRequest" + "$ref": "#/components/schemas/QueryExploreRequest" }, "example": { - "member_id": 5068740052131, - "role_ids": [ - 6 - ] + "datasource_id": 101, + "expr": "rate(http_requests_total[5m])", + "args": {}, + "execution": { + "kind": "range", + "from_ms": 1787187600000, + "to_ms": 1787191200000, + "max_data_points": 1200, + "min_step_seconds": 15 + } } } } - } - } - }, - "/member/role/update": { - "post": { - "operationId": "memberUpdateRole", - "summary": "Update member roles", - "description": "Replace a member's role assignments with the given set of roles.", - "tags": [ - "Platform/Members" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Members Manage** (`organization`) |\n\n## Usage\n\n- An empty or omitted `role_ids` assigns the built-in Viewer role (`8`).\n- Role IDs that do not exist are dropped; if none of the given IDs exist, the member ends up with no roles.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/members/member-update-role", - "metadata": { - "sidebarTitle": "Update member roles" - } }, "responses": { "200": { @@ -48317,7 +51041,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/MemberEmptyObject" + "$ref": "#/components/schemas/ExploreData" } } } @@ -48325,59 +51049,173 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "format": "explore_result.v1", + "result": { + "kind": "frames", + "frames": [ + { + "kind": "time_series", + "fields": [ + { + "name": "time", + "type": "time", + "values": [ + "2026-08-20T10:00:00Z", + "2026-08-20T10:01:00Z" + ] + }, + { + "name": "value", + "type": "float", + "labels": { + "job": "api" + }, + "values": [ + 1.25, + null + ] + } + ] + } + ] + }, + "execution": { + "kind": "range", + "effective_step_seconds": 60 + } + } } } } }, "400": { - "$ref": "#/components/responses/BadRequest" + "description": "Standard HTTP error. `error.reason` is `invalid_request` for malformed or out-of-range parameters, a disabled data source, an unsupported data source type, or a data source without an Edge cluster. A data source ID that does not exist returns code `ResourceNotFound` without a `reason`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { - "$ref": "#/components/responses/Forbidden" + "description": "The caller is not allowed to query this data source. `error.code` is `AccessDenied`; there is no `error.reason`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "413": { + "description": "Standard HTTP error. `error.reason`: `too_many_rows`, `source_too_large`, or `result_too_large`. A request body above 256 KiB also returns 413, without a `reason`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, "429": { - "$ref": "#/components/responses/TooManyRequests" + "description": "Standard HTTP error; error.reason: overloaded.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "499": { + "description": "Standard HTTP error; error.reason: canceled.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } }, "500": { - "$ref": "#/components/responses/ServerError" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MemberRoleUpdateRequest" - }, - "example": { - "member_id": 5068740052131, - "role_ids": [ - 2, - 6 - ] + "description": "Standard HTTP error; error.reason: internal.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Standard HTTP error. `error.reason`: `no_active_edge`, `edge_version_unknown`, `edge_upgrade_required`, `mixed_edge_versions`, or `edge_unavailable`.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "504": { + "description": "Standard HTTP error; error.reason: timeout.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } + }, + "summary": "Run Explore query", + "tags": [ + "Monitors/Diagnostics" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **16 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n| Edge requirement | Supported deployments require **monit-edge v0.68.0 or later** |\n\n## Usage\n\n- Use this endpoint when you need the data source's native result shape; `/monit/query/data` returns the stable `query_result.v1` contract instead. Dispatch on `data.result.kind` (`frames`, `samples`, or `logs`) here.\n- The data source is identified by `datasource_id`. It must belong to the account, be enabled, have an Edge cluster, and be one of `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `victorialogs`, or `tencent_cls`. When the data source restricts querying to certain teams, only members of those teams, its managing team, and account owners or admins can query it.\n- `execution.kind` decides which companion fields are accepted: `instant` needs `to_ms` (`from_ms` is optional), `range` requires `from_ms`, `to_ms`, and `max_data_points`, and `window` requires `from_ms` and `to_ms`. When both times are given, `from_ms` must be less than `to_ms`. `step_seconds` is not accepted; the step is derived from `max_data_points` and `min_step_seconds`.\n- `args` is required (send `{}` when unused) and carries macro substitutions such as Grafana-style variables; every value is a string. Unknown or duplicate JSON keys are rejected.\n- A `logs` result is capped at 1,000 entries (100 for `sls`) and reports `applied_limit` plus `has_more`. A `frames` result holds at most 1,000 frames, 1,000 table rows in total, and 100,000 values in total; a `samples` result holds at most 1,000 samples. The request body is limited to 256 KiB and the whole success response to 10 MiB.\n- Failures use the standard error envelope. `error.reason` is a stable machine-readable value; a data source ID that does not exist returns HTTP 400 with code `ResourceNotFound` and no `reason`.\n- Query execution may take up to 35 seconds across WebAPI forwarding and Edge execution. Configure client timeouts to at least 40 seconds.", + "href": "/en/api-reference/monitors/diagnostics/monit-read-query-explore", + "metadata": { + "sidebarTitle": "Run Explore query" + } } } }, - "/monit/datasource/create": { + "/monit/query/data": { "post": { - "operationId": "monit-datasource-write-create", - "summary": "Create datasource", - "description": "Create a monitoring datasource of one of 15 supported types and bind it to a Monitors edge cluster.", + "operationId": "monit-read-query-data", + "summary": "Query structured data", + "description": "Run a synchronous ad-hoc query against a data source and return a `query_result.v1` result as frames, records, or samples.", "tags": [ - "Monitors/Data sources" + "Monitors/Diagnostics" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- `type_ident` must be one of: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`. The last five (`redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`) are diagnostic-only: they cannot evaluate alerts, so `alerting_enabled` must not be `true`.\n- `name` must be unique within the account across all types; a duplicate fails with `InvalidParameter`.\n- `edge_cluster_name` must be an existing Monitors edge cluster of the account; that cluster evaluates rules and runs queries for the datasource.\n- Put the type-specific settings in `payload.`. For `elasticsearch`, `payload.elasticsearch.deployment` is required (`cloud` or `self-managed`). `tencent_cls` requires every edge instance in the cluster to run Monitors edge v0.66.0 or later.\n- Omitted `enabled` defaults to `true`; omitted `alerting_enabled` defaults to `true` for alerting types and `false` for diagnostic-only types. Explicit `null` for either is rejected.\n- `manage_team_id` and `readonly_team_ids` restrict who can manage or query the datasource; omit both to leave it open to every member.\n- Responses return credentials of non-diagnostic types (for example Prometheus Basic Auth passwords) as stored. Diagnostic passwords and Kafka private keys are returned only when they are `${env:NAME}` references. Treat responses as sensitive.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **5 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n| Edge requirement | Supported deployments require **monit-edge v0.65.0 or later** |\n\n## Usage\n\n- The data source is identified by `ds_type` plus `ds_name`, not by ID. It must belong to the account and be enabled. When the data source restricts querying to certain teams, only members of those teams, its managing team, and account owners or admins can query it; others get `AccessDenied`.\n- Treat **monit-edge v0.65.0** as the minimum supported Edge version for this public API. WebAPI retains migration adapters for older Edge versions: query.v2 results may still preserve frames, records, or samples, while legacy rows can expose only the information they retained. These adapters do not change the support floor; older protocols lack query.v3 cancellation and error-lifecycle semantics, and data already lost by legacy rows cannot be recovered.\n- The public response format is always `query_result.v1` and is independent of the internal Edge query protocol. Dispatch on `result.kind` (`frames`, `records`, or `samples`); do not infer the result shape from `ds_type` or the Edge version.\n- A `frames` result may contain multiple table or time-series frames. Field values are columnar and all fields in one frame have the same length.\n- A `records` result may contain nested JSON and null records. Integer literals outside JavaScript's safe integer range are returned as decimal strings.\n- A `samples` result contains label sets and instant values. A value may be a number or one of the strings `NaN`, `+Inf`, and `-Inf`.\n- Prometheus expressions are syntax-checked before the query is dispatched; an invalid expression returns HTTP 400.\n- The request body is limited to 256 KiB and the complete success response to 10 MiB; either limit returns HTTP 413. A result with more than 1,000 rows fails with HTTP 400. Narrow the time range, reduce fields, or aggregate at the source.\n- Query failures use non-2xx HTTP status codes and the standard error envelope.\n- Query execution may take up to 35 seconds across WebAPI forwarding and Edge execution. Configure client timeouts to at least 40 seconds and propagate cancellation when the caller abandons a query.", + "href": "/en/api-reference/monitors/diagnostics/monit-read-query-data", "metadata": { - "sidebarTitle": "Create datasource" + "sidebarTitle": "Query structured data" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/QueryDataRequest" + }, + "example": { + "ds_type": "prometheus", + "ds_name": "prod-prom", + "expr": "sum by (job) (rate(http_requests_total[5m]))", + "delay_seconds": 0, + "args": {} + } + } } }, "responses": { @@ -48394,7 +51232,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/DataSourceItem" + "$ref": "#/components/schemas/QueryDataResponse" } } } @@ -48403,27 +51241,18 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "id": 10, - "account_id": 10023, - "type_ident": "prometheus", - "name": "Prometheus Prod", - "enabled": true, - "note": "Production Prometheus", - "address": "http://prometheus.example.com:9090", - "payload": { - "prometheus": { - "basic_auth_enabled": false, - "basic_auth_username": "", - "basic_auth_password": "", - "tls_skip_verify": false - } - }, - "edge_cluster_name": "default", - "updated_at": 1712000000, - "alerting_enabled": true, - "manage_team_id": null, - "readonly_team_ids": null, - "creator_id": 20001 + "format": "query_result.v1", + "result": { + "kind": "samples", + "samples": [ + { + "labels": { + "job": "api" + }, + "value": 1.25 + } + ] + } } } } @@ -48438,30 +51267,41 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "413": { + "description": "The request or final response exceeds its size limit.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, + "499": { + "description": "The client canceled the query.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, "500": { "$ref": "#/components/responses/ServerError" - } - }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DataSourceUpsertRequest" - }, - "example": { - "type_ident": "prometheus", - "name": "Prometheus Prod", - "note": "Production Prometheus", - "address": "http://prometheus.example.com:9090", - "edge_cluster_name": "default", - "payload": { - "prometheus": { - "basic_auth_enabled": false - } + }, + "503": { + "$ref": "#/components/responses/ServiceUnavailable" + }, + "504": { + "description": "The query timed out.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" } } } @@ -48469,19 +51309,19 @@ } } }, - "/monit/datasource/delete": { + "/monit/rule/audit/detail": { "post": { - "operationId": "monit-datasource-write-delete", - "summary": "Delete datasource", - "description": "Delete a datasource by ID; alert rules that reference it are not blocked.", + "operationId": "monit-rule-read-audit-detail", + "summary": "Get rule audit snapshot", + "description": "Return one audit record of an alert rule, including the rule snapshot stored in `content`.", "tags": [ - "Monitors/Data sources" + "Monitors/Alert rules" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- Alert rules that reference the datasource are not blocked or edited; their open alerts on it are closed automatically.\n- Deleting an ID that does not exist succeeds as a no-op; an ID in another account returns `ResourceNotFound`.\n- Only the account owner, Admin members, the creator and members of the managing team can delete a datasource (anyone with the permission when no managing team is set); others get `AccessDenied`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-delete", + "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- Pass the audit record `id` (not the rule `id`) from `POST /monit/rule/audits`. An unknown ID returns `InvalidParameter` (`alert rule audit not found`).\n- `content` is a JSON string — parse it to get the rule snapshot; its shape depends on the operation that wrote the record (see `content` below).\n- To read a record, the caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`. Records of a deleted rule can no longer be read: the call returns `InvalidParameter` (`alert rule not found`).", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-audit-detail", "metadata": { - "sidebarTitle": "Delete datasource" + "sidebarTitle": "Get rule audit snapshot" } }, "responses": { @@ -48498,7 +51338,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/AlertRuleAudit" } } } @@ -48506,7 +51346,16 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "id": 9001, + "account_id": 888, + "alert_rule_id": 50001, + "action": "update", + "content": "{\"id\":50001,\"account_id\":888,\"folder_id\":100,\"name\":\"CPU High\",\"enabled\":true,\"updated_at\":1712003600}", + "creator_id": 66, + "creator_name": "zhangsan", + "created_at": 1712003600 + } } } } @@ -48532,29 +51381,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IDRequest" + "$ref": "#/components/schemas/AuditRecordIDRequest" }, "example": { - "id": 10 + "id": 9001 } } } } } }, - "/monit/datasource/info": { + "/monit/rule/audits": { "post": { - "operationId": "monit-datasource-read-info", - "summary": "Get datasource detail", - "description": "Return one datasource by ID, including its full `payload` configuration.", + "operationId": "monit-rule-read-audits", + "summary": "List rule change history", + "description": "Return the change history (audit records) for an alert rule.", "tags": [ - "Monitors/Data sources" + "Monitors/Alert rules" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- Requires manage access to the datasource (see `manage_team_id`); members who can only query it get `AccessDenied`. Use `/monit/datasource/list` for the datasources you can query.\n- The response is sensitive: `payload` holds connection settings, and credentials of non-diagnostic types are returned as stored. Diagnostic passwords and Kafka private keys are returned only when they are `${env:NAME}` references; `tencent_cls` `secret_key` is returned as an empty string unless it is a `${env:NAME}` reference.\n- An unknown ID, or one in another account, returns `ResourceNotFound`.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-info", + "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- Records are ordered newest first and omit `content`; read one snapshot with `POST /monit/rule/audit/detail`.\n- A record is written on every create, full update, field update and move. Deleting a rule writes no record, and the history of a deleted rule can no longer be listed: the call returns `InvalidParameter` (`alert rule not found`).\n- The caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-audits", "metadata": { - "sidebarTitle": "Get datasource detail" + "sidebarTitle": "List rule change history" } }, "responses": { @@ -48571,7 +51420,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/DataSourceItem" + "$ref": "#/components/schemas/RuleAuditListResponse" } } } @@ -48579,29 +51428,26 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "id": 10, - "account_id": 10023, - "type_ident": "prometheus", - "name": "Prometheus Prod", - "enabled": true, - "note": "Production Prometheus", - "address": "http://prometheus.example.com:9090", - "payload": { - "prometheus": { - "basic_auth_enabled": false, - "basic_auth_username": "", - "basic_auth_password": "", - "tls_skip_verify": false - } + "data": [ + { + "id": 9001, + "account_id": 888, + "alert_rule_id": 50001, + "action": "update", + "creator_id": 66, + "creator_name": "zhangsan", + "created_at": 1712003600 }, - "edge_cluster_name": "default", - "updated_at": 1712000000, - "alerting_enabled": true, - "manage_team_id": null, - "readonly_team_ids": null, - "creator_id": 20001 - } + { + "id": 8990, + "account_id": 888, + "alert_rule_id": 50001, + "action": "create", + "creator_id": 66, + "creator_name": "zhangsan", + "created_at": 1712000000 + } + ] } } } @@ -48627,72 +51473,56 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/IDRequest" + "$ref": "#/components/schemas/RuleIDRequest" }, "example": { - "id": 10 + "id": 50001 } } } } } }, - "/monit/datasource/list": { + "/monit/rule/counter/channel": { "post": { - "operationId": "monit-datasource-read-list", - "summary": "List datasources", - "description": "List the account's datasources that the caller can query, optionally filtered by type or exact name.", + "operationId": "monit-rule-read-counter-channel", + "summary": "Get rule counts by channel", + "description": "Return how many alert rules route alerts to each collaboration space, keyed by space name.", "tags": [ - "Monitors/Data sources" + "Monitors/Alert rules" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- Omit `type` and `name` to return every datasource you can query; `type` and `name` are exact-match filters. An unrecognized `type` returns an empty array. The result is not paginated.\n- Only datasources the caller can query are returned (see `readonly_team_ids`); each item carries `my_perm` (`manage` or `readonly`).\n- `payload` is always `null` in list items. Use `/monit/datasource/info` to read the configuration of a datasource you can manage.\n- `address` in list items has userinfo (`user:password@`), the query string and the fragment removed from each comma-separated entry. `/monit/datasource/info` returns the address as stored.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Monits Overview Read** (`monit`) |\n\n## Usage\n\n- Only rules with a non-empty `channel_ids` are counted; a rule routed to several spaces is counted once under each of them.\n- When a space ID cannot be resolved to a name, the ID (as a string) is used as the key. Spaces that share the same name are merged into one key.\n- Returns an empty object `{}` when no rule routes to a space.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-counter-channel", "metadata": { - "sidebarTitle": "List datasources" + "sidebarTitle": "Get rule counts by channel" } }, "responses": { "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/components/schemas/DataSourceListResponse" - } - } - } - ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": [ - { - "id": 10, - "account_id": 10023, - "type_ident": "prometheus", - "name": "Prometheus Prod", - "enabled": true, - "note": "Production Prometheus", - "address": "http://prometheus.example.com:9090", - "payload": null, - "edge_cluster_name": "default", - "updated_at": 1712000000, - "alerting_enabled": true, - "manage_team_id": null, - "readonly_team_ids": null, - "creator_id": 20001, - "my_perm": "manage" + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/RuleCounterChannelResponse" + } + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "Production": 8 + } } } } @@ -48718,29 +51548,27 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DataSourceListRequest" + "$ref": "#/components/schemas/RuleEmptyRequest" }, - "example": { - "type": "prometheus" - } + "example": {} } } } } }, - "/monit/datasource/sls/logstores": { + "/monit/rule/counter/total": { "post": { - "operationId": "monit-datasource-read-sls-logstores", - "summary": "List SLS logstores", - "description": "List logstores within an SLS project for the specified SLS datasource.", + "operationId": "monit-rule-read-counter-total", + "summary": "Get rule counter time series", + "description": "Return the stored time series of the total rule count across the account — one sample per `clock` timestamp.", "tags": [ - "Monitors/Data sources" + "Monitors/Alert rules" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- The datasource identified by `id` must be of type `sls`; other types fail with `InvalidParameter`.\n- The caller needs query access to the datasource (see `readonly_team_ids` on the datasource); otherwise the call fails with 403 `AccessDenied`.\n- Supply `project` to select the SLS project whose logstores to list; use `offset` and `size` to paginate. The response is a plain array of logstore names.\n- The request is relayed to the Monitors edge cluster of the datasource, which calls Alibaba Cloud with the stored credentials; it times out after 30 seconds. Fails with `InvalidParameter` when no edge instance of that cluster is online, and with HTTP 503 `ServiceUnavailable` when the edge version does not support metadata discovery.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-sls-logstores", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Monits Overview Read** (`monit`) |\n\n## Usage\n\n- Each item is a historical snapshot: `num` is the total number of alert rules in the account (enabled and disabled) at `clock` (Unix timestamp in seconds).\n- A snapshot is recorded roughly every 12 hours (an hourly job adds one when none exists in the last 12 hours). All snapshots are returned oldest first; the array is empty until the first snapshot is recorded.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-counter-total", "metadata": { - "sidebarTitle": "List SLS logstores" + "sidebarTitle": "Get rule counter time series" } }, "responses": { @@ -48757,7 +51585,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/SLSLogstoresResponse" + "$ref": "#/components/schemas/RuleCounterTotalResponse" } } } @@ -48766,8 +51594,18 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": [ - "logstore-1", - "logstore-2" + { + "id": 1, + "account_id": 888, + "num": 48, + "clock": 1711956000 + }, + { + "id": 2, + "account_id": 888, + "num": 50, + "clock": 1712000000 + } ] } } @@ -48794,32 +51632,27 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SLSLogstoresRequest" + "$ref": "#/components/schemas/RuleEmptyRequest" }, - "example": { - "id": 10, - "project": "project-a", - "offset": 0, - "size": 50 - } + "example": {} } } } } }, - "/monit/datasource/sls/projects": { + "/monit/rule/delete": { "post": { - "operationId": "monit-datasource-read-sls-projects", - "summary": "List SLS projects", - "description": "List Alibaba Cloud SLS (Simple Log Service) projects available in the specified SLS datasource.", + "operationId": "monit-rule-write-delete", + "summary": "Delete alert rule", + "description": "Delete a single alert rule by its ID.", "tags": [ - "Monitors/Data sources" + "Monitors/Alert rules" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- The datasource identified by `id` must be of type `sls`; other types fail with `InvalidParameter`.\n- The caller needs query access to the datasource (see `readonly_team_ids` on the datasource); otherwise the call fails with 403 `AccessDenied`.\n- Use `query` to filter the project list and `offset` and `size` to paginate; `count` is the number of projects in the page and `total` the number matching the filter.\n- The request is relayed to the Monitors edge cluster of the datasource, which calls Alibaba Cloud with the stored credentials; it times out after 30 seconds. Fails with `InvalidParameter` when no edge instance of that cluster is online, and with HTTP 503 `ServiceUnavailable` when the edge version does not support metadata discovery.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-sls-projects", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- The rule's active alerts are cleared as part of the deletion.\n- Deleting an ID that does not exist succeeds with an empty `data`, so retries are safe.\n- The caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-delete", "metadata": { - "sidebarTitle": "List SLS projects" + "sidebarTitle": "Delete alert rule" } }, "responses": { @@ -48836,7 +51669,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/SLSProjectsResponse" + "$ref": "#/components/schemas/RuleEmptyResponse" } } } @@ -48844,30 +51677,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "projects": [ - { - "projectName": "project-a", - "description": "Production logs", - "status": "Normal", - "owner": "", - "region": "cn-shanghai", - "createTime": "1710000000", - "lastModifyTime": "1712000000" - }, - { - "projectName": "project-b", - "description": "Staging logs", - "status": "Normal", - "owner": "", - "region": "cn-shanghai", - "createTime": "1710000000", - "lastModifyTime": "1712000000" - } - ], - "count": 2, - "total": 2 - } + "data": {} } } } @@ -48893,57 +51703,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SLSProjectsRequest" + "$ref": "#/components/schemas/RuleIDRequest" }, "example": { - "id": 10, - "query": "", - "offset": 0, - "size": 50 + "id": 50001 } } } } } }, - "/monit/datasource/tools/invoke": { + "/monit/rule/delete/batch": { "post": { - "description": "Execute one deterministic diagnostic or query tool against a configured datasource.", - "operationId": "monit-datasource-tools-invoke", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DatasourceToolInvokeRequest" - }, - "examples": { - "diagnostic": { - "value": { - "datasource_id": 10, - "params": {}, - "tool": "mysql.overview" - } - }, - "query": { - "value": { - "datasource_id": 24000, - "tool": "prometheus.query", - "params": { - "expr": "sum(rate(http_requests_total[5m]))", - "execution": { - "kind": "instant", - "to_ms": 1789000000000 - } - } - } - } - } - } - }, - "required": true + "operationId": "monit-rule-write-delete-batch", + "summary": "Batch delete alert rules", + "description": "Delete multiple alert rules in a single request.", + "tags": [ + "Monitors/Alert rules" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **5 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- IDs are processed in order and the call stops at the first error; rules deleted before the error stay deleted, so fix the cause and re-send the remaining IDs.\n- IDs that do not exist are skipped without error. Each deleted rule's active alerts are cleared.\n- `ids` must contain at least one ID. For every rule, the caller must be able to manage its folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-delete-batch", + "metadata": { + "sidebarTitle": "Batch delete alert rules" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { "schema": { @@ -48952,188 +51739,69 @@ "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/DatasourceToolResult" + "$ref": "#/components/schemas/RuleEmptyResponse" } - }, - "type": "object" + } } ] }, - "examples": { - "diagnostic": { - "value": { - "data": { - "data": { - "version": "8.0.36" - }, - "datasource_id": 10, - "summary": "MySQL overview", - "tool": "mysql.overview" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - } - }, - "query": { - "value": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "datasource_id": 24000, - "tool": "prometheus.query", - "data": { - "format": "explore_result.v1", - "result": { - "kind": "samples", - "samples": [ - { - "labels": { - "__name__": "up", - "instance": "203.0.113.10:9090" - }, - "value": 1 - } - ] - } - } - } - } - } + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: invalid_request, tool_not_supported, datasource_error." + "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: access_denied." - }, - "404": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: datasource_not_found." - }, - "409": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: datasource_disabled, datasource_in_use." - }, - "413": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: source_too_large, result_too_large." + "$ref": "#/components/responses/Forbidden" }, "429": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: overloaded." - }, - "499": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: canceled." + "$ref": "#/components/responses/TooManyRequests" }, "500": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: internal." - }, - "503": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: no_active_edge, edge_upgrade_required, mixed_edge_versions." - }, - "504": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - }, - "description": "Standard HTTP error; error.reason: timeout." + "$ref": "#/components/responses/ServerError" } }, - "summary": "Invoke datasource tool", - "tags": [ - "Monitors/Data sources" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **2,000 requests/minute**; **32 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\nUse datasource IDs from `/monit/datasource/list`. Disabled datasources return `datasource_disabled`; `alerting_enabled=false` does not block tools. Errors use non-2xx HTTP status and `error.code`, `error.message`, `error.reason`. `tool_not_supported` indicates the selected executor does not provide this tool; it is not a vendor permission error. Never retry through another Edge or the legacy diagnose endpoint automatically.\n\n## Usage\n\n- The caller needs query access to the datasource (see `readonly_team_ids` on the datasource); without it the call fails with 403 `access_denied`. A datasource in another account returns 404 `datasource_not_found`.\n- Diagnostic tools exist only for datasource types `mysql`, `postgres`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`, `elasticsearch`, `prometheus`, `loki` and `victorialogs`; `oracle`, `clickhouse`, `sls` and `tencent_cls` support only their `.query` tool. Other combinations fail with `invalid_request`.\n- Two tool families share this entry: diagnostic tools defined by the executing Edge (e.g. `mysql.overview`, `prometheus.metric_trends`) and query tools named `.query`. The tool prefix must match the datasource type.\n- Query tools require the Edge cluster to support Explore queries (protocol milestone v0.68.0); diagnostic tools require the v0.71.0 base invoke protocol. Unsupported clusters fail with `edge_upgrade_required`, `mixed_edge_versions`, or `edge_version_unknown`; never fall back to `/monit/query/data` or another endpoint automatically.\n- For query tools, `params` follows the per-datasource schema named in the `tool` field description. `expr` and `execution` are always required. `limit`/`direction` only bound raw-log retrieval, never SQL rows or scanned data. Unknown extension fields are tolerated but never executed or forwarded.\n- Query `data` is the complete Explore result: `format` is `explore_result.v1` and `result.kind` is `samples`, `frames`, or `logs`; log results keep `applied_limit` and `has_more`. Query results never synthesize `summary` or `truncated`.\n- Request body limit 128 KiB; complete success response limit 10 MiB for both families; diagnostic tool timeout at most 25 seconds.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-tools-invoke", - "metadata": { - "sidebarTitle": "Invoke datasource tool" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RuleIDsRequest" + }, + "example": { + "ids": [ + 50001, + 50002 + ] + } + } } } } }, - "/monit/datasource/update": { + "/monit/rule/list/basic": { "post": { - "operationId": "monit-datasource-write-update", - "summary": "Update datasource", - "description": "Update a datasource by ID, replacing its name, note, address, payload and edge cluster.", + "operationId": "monit-rule-read-list", + "summary": "List alert rules", + "description": "Return basic information for the alert rules in a folder; call `POST /monit/rule/v2/info` for full details.", "tags": [ - "Monitors/Data sources" + "Monitors/Alert rules" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- This is a full replace, not a patch: send `type_ident`, `name`, `edge_cluster_name`, `payload` and (except for Elasticsearch `cloud`) `address` on every call. `note`, `address` and `payload` overwrite the stored values, so an omitted `note` is cleared.\n- Omitting `enabled`, `alerting_enabled`, `manage_team_id` or `readonly_team_ids` keeps the current value. `null` for `enabled` or `alerting_enabled` is rejected; `null` for the two team fields clears them.\n- Secrets: for the diagnostic types, omit the password (and the Kafka `tls_key`) to keep the stored value or send an empty string to clear it. For `tencent_cls`, an omitted or empty `secret_key` keeps the stored key. Other types need their credentials resent.\n- Setting `enabled` or `alerting_enabled` to `false`, or changing `type_ident` or `edge_cluster_name`, closes open alerts of the rules that use this datasource. Renaming it closes open alerts of rules whose `ds_list` name pattern no longer matches the new name.\n- Turning `alerting_enabled` off fails with HTTP 409 `UndonedOrderExist` while an enabled alert rule still selects the datasource.\n- Only the account owner, Admin members, the creator and members of the managing team can update a datasource (anyone with the permission when no managing team is set); others get `AccessDenied`. An unknown ID, or one in another account, returns `ResourceNotFound`.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Alerting Rules Read** or **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `folder_id` must be an existing folder: `0` or an unknown ID returns `InvalidParameter`, and a folder the caller cannot manage (account owner or admin, creator of the folder or an ancestor, or member of the team bound to it or an ancestor) returns `AccessDenied`. There is no account-wide listing.\n- By default only the rules directly in the folder are returned, sorted by name, with `active_alert_count` and `runtime_state` filled.\n- With `include_descendants: true` the call searches the folder and all its descendant folders and returns at most `limit` rules sorted by name; only `id`, `folder_id` and `name` are filled and the other fields carry zero values (`labels` is `null`, `runtime_state` is omitted).\n- `triggered` is `true` exactly when `active_alert_count > 0`.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-list", "metadata": { - "sidebarTitle": "Update datasource" + "sidebarTitle": "List alert rules" } }, "responses": { @@ -49150,7 +51818,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/DataSourceItem" + "$ref": "#/components/schemas/RuleBasicListResponse" } } } @@ -49158,29 +51826,32 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "id": 10, - "account_id": 10023, - "type_ident": "prometheus", - "name": "Prometheus Prod v2", - "enabled": true, - "note": "Updated", - "address": "http://prometheus-v2.example.com:9090", - "payload": { - "prometheus": { - "basic_auth_enabled": false, - "basic_auth_username": "", - "basic_auth_password": "", - "tls_skip_verify": false - } - }, - "edge_cluster_name": "default", - "updated_at": 1712100000, - "alerting_enabled": true, - "manage_team_id": null, - "readonly_team_ids": null, - "creator_id": 20001 - } + "data": [ + { + "id": 50001, + "account_id": 888, + "folder_id": 100, + "name": "CPU High", + "labels": { + "team": "sre" + }, + "ds_type": "prometheus", + "enabled": true, + "debug_log_enabled": false, + "cron_pattern": "0 * * * * *", + "timezone": "Asia/Shanghai", + "delay_seconds": 0, + "creator_id": 66, + "creator_name": "zhangsan", + "updater_id": 66, + "updater_name": "zhangsan", + "created_at": 1710000000, + "updated_at": 1712000000, + "triggered": true, + "active_alert_count": 2, + "runtime_state": "normal" + } + ] } } } @@ -49206,78 +51877,69 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/DataSourceUpsertRequest" + "$ref": "#/components/schemas/RuleListRequest" }, "example": { - "id": 10, - "type_ident": "prometheus", - "name": "Prometheus Prod v2", - "note": "Updated", - "address": "http://prometheus-v2.example.com:9090", - "edge_cluster_name": "default", - "payload": { - "prometheus": { - "basic_auth_enabled": false - } - } + "folder_id": 100 } } } } } }, - "/monit/prometheus/api/v1/label/{label_name}/values": { - "get": { - "description": "Read label values from a Prometheus-compatible data source through the Monitors proxy.", - "operationId": "monit-prometheus-read-label-values", - "parameters": [ - { - "name": "label_name", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "Label name to enumerate values for, for example `job`." - }, - { - "name": "X-DSID", - "in": "header", - "required": false, - "schema": { - "type": "string" - }, - "description": "Data source ID to query, as a decimal string. Must reference a Prometheus data source owned by the authenticated account. When omitted, the request is served by the platform's own Prometheus instead of one of your data sources." - } + "/monit/rule/move": { + "post": { + "operationId": "monit-rule-write-move", + "summary": "Move alert rules to folder", + "description": "Move one or more alert rules to a different folder.", + "tags": [ + "Monitors/Alert rules" ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `dest_folder_id` must be an existing folder that the caller must be able to manage the folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the whole call fails with `AccessDenied` and nothing is moved.\n- The result has one entry per requested ID, in request order. A moved rule's `message` is a localized success text (`Move successfully` / `移动成功`); a rule that is not moved stays in its folder and its `message` carries the error.\n- A rule is not moved when a rule with the same name already exists in the destination folder, when the caller cannot manage its current folder, or when the ID does not exist (its `name` is then `id: `).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-move", + "metadata": { + "sidebarTitle": "Move alert rules to folder" + } + }, "responses": { "200": { - "description": "Native Prometheus label-values response returned by the data source.", + "description": "Success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PrometheusLabelValuesResponse" + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/RuleNameMessageListResponse" + } + } + } + ] }, "example": { - "status": "success", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": [ - "api", - "db", - "worker" + { + "name": "CPU High", + "message": "Move successfully" + }, + { + "name": "Disk High", + "message": "alert rule name already exists in this folder" + } ] } } } }, "400": { - "description": "The `X-DSID` header is not a number, the data source is not a Prometheus data source, no monit-edge is registered for the data source's cluster, or the data source does not exist or belongs to another account (message `data source not found`). Returned as `text/plain`.", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } + "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" @@ -49287,56 +51949,44 @@ }, "429": { "$ref": "#/components/responses/TooManyRequests" - }, - "500": { - "description": "The data source lookup or proxied request failed. Returned as `text/plain`.", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - } - }, - "summary": "List Prometheus label values", - "tags": [ - "Monitors/Data sources" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n| Edge requirement | Querying a specific data source requires **monit-edge v0.35.0 or later** |\n\n## Usage\n\n- Pass the target data source ID in the `X-DSID` header. It must belong to the authenticated account and be a Prometheus data source; use `/monit/datasource/list` to obtain its ID.\n- When the data source restricts querying to certain teams, only members of those teams, its managing team, and account owners or admins can query it; others get 403. An unknown data source ID returns 400.\n- The 200 body is the data source's native Prometheus HTTP API payload, **not** the standard `{ request_id, data }` envelope. Query-string parameters are forwarded unchanged, so Prometheus's own parameters such as `match[]`, `start`, and `end` work.\n- When `X-DSID` is omitted, or any monit-edge of the data source's cluster is older than v0.35.0, the request is answered by the platform's own Prometheus instead of your data source. Send the header and keep monit-edge up to date to get your data source's values.\n- Failures raised before the data source is reached are returned as `text/plain` with the matching 4xx or 5xx status. A status of 400 or above returned by the data source itself is passed through with its own body.", - "href": "/en/api-reference/monitors/data-sources/monit-prometheus-read-label-values", - "metadata": { - "sidebarTitle": "List Prometheus label values" + }, + "500": { + "$ref": "#/components/responses/ServerError" } - } - } - }, - "/monit/query/explore": { - "post": { - "description": "Run an Explore query against a configured data source and return frames, samples, or logs.", - "operationId": "monit-read-query-explore", + }, "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/QueryExploreRequest" + "$ref": "#/components/schemas/RuleMoveRequest" }, "example": { - "datasource_id": 101, - "expr": "rate(http_requests_total[5m])", - "args": {}, - "execution": { - "kind": "range", - "from_ms": 1787187600000, - "to_ms": 1787191200000, - "max_data_points": 1200, - "min_step_seconds": 15 - } + "ids": [ + 50001, + 50002 + ], + "dest_folder_id": 200 } } } + } + } + }, + "/monit/rule/update/fields": { + "post": { + "operationId": "monit-rule-write-fields-update", + "summary": "Batch update rule fields", + "description": "Update the fields listed in `fields` on multiple alert rules in one call.", + "tags": [ + "Monitors/Alert rules" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- Each listed field takes the value of the same-named request field; a listed field whose value is omitted is set to its zero value (for example, listing `labels` without `labels` or `labels_patch` removes all labels). Unlisted fields keep their current values.\n- An unknown name in `fields`, a `labels_patch` / `annotations_patch` whose field is not listed in `fields`, or sending `labels` together with `labels_patch` (or `annotations` with `annotations_patch`) fails the whole call with `InvalidParameter`.\n- Rules are updated one by one and the result has one entry per ID: `message` is empty on success, otherwise it carries that rule's error (validation failure, no access to its folder, or an unknown ID, whose `name` is then `id: `).\n- Setting `enabled` to `false` clears the rules' active alerts. Unless the call only disables rules (`fields` is exactly `[\"enabled\"]` with `enabled: false`), it fails with `AccessDenied` when the account exceeds its alert rule license limit, and non-admin callers need read-only access to every datasource each rule selects.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-fields-update", + "metadata": { + "sidebarTitle": "Batch update rule fields" + } }, "responses": { "200": { @@ -49352,7 +52002,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ExploreData" + "$ref": "#/components/schemas/RuleNameMessageListResponse" } } } @@ -49360,156 +52010,34 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "format": "explore_result.v1", - "result": { - "kind": "frames", - "frames": [ - { - "kind": "time_series", - "fields": [ - { - "name": "time", - "type": "time", - "values": [ - "2026-08-20T10:00:00Z", - "2026-08-20T10:01:00Z" - ] - }, - { - "name": "value", - "type": "float", - "labels": { - "job": "api" - }, - "values": [ - 1.25, - null - ] - } - ] - } - ] + "data": [ + { + "name": "CPU High", + "message": "" }, - "execution": { - "kind": "range", - "effective_step_seconds": 60 + { + "name": "Disk High", + "message": "" } - } + ] } } } }, "400": { - "description": "Standard HTTP error. `error.reason` is `invalid_request` for malformed or out-of-range parameters, a disabled data source, an unsupported data source type, or a data source without an Edge cluster. A data source ID that does not exist returns code `ResourceNotFound` without a `reason`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { - "description": "The caller is not allowed to query this data source. `error.code` is `AccessDenied`; there is no `error.reason`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "413": { - "description": "Standard HTTP error. `error.reason`: `too_many_rows`, `source_too_large`, or `result_too_large`. A request body above 256 KiB also returns 413, without a `reason`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "$ref": "#/components/responses/Forbidden" }, "429": { - "description": "Standard HTTP error; error.reason: overloaded.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "499": { - "description": "Standard HTTP error; error.reason: canceled.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } + "$ref": "#/components/responses/TooManyRequests" }, "500": { - "description": "Standard HTTP error; error.reason: internal.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "503": { - "description": "Standard HTTP error. `error.reason`: `no_active_edge`, `edge_version_unknown`, `edge_upgrade_required`, `mixed_edge_versions`, or `edge_unavailable`.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "504": { - "description": "Standard HTTP error; error.reason: timeout.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "summary": "Run Explore query", - "tags": [ - "Monitors/Diagnostics" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **16 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n| Edge requirement | Supported deployments require **monit-edge v0.68.0 or later** |\n\n## Usage\n\n- Use this endpoint when you need the data source's native result shape; `/monit/query/data` returns the stable `query_result.v1` contract instead. Dispatch on `data.result.kind` (`frames`, `samples`, or `logs`) here.\n- The data source is identified by `datasource_id`. It must belong to the account, be enabled, have an Edge cluster, and be one of `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `victorialogs`, or `tencent_cls`. When the data source restricts querying to certain teams, only members of those teams, its managing team, and account owners or admins can query it.\n- `execution.kind` decides which companion fields are accepted: `instant` needs `to_ms` (`from_ms` is optional), `range` requires `from_ms`, `to_ms`, and `max_data_points`, and `window` requires `from_ms` and `to_ms`. When both times are given, `from_ms` must be less than `to_ms`. `step_seconds` is not accepted; the step is derived from `max_data_points` and `min_step_seconds`.\n- `args` is required (send `{}` when unused) and carries macro substitutions such as Grafana-style variables; every value is a string. Unknown or duplicate JSON keys are rejected.\n- A `logs` result is capped at 1,000 entries (100 for `sls`) and reports `applied_limit` plus `has_more`. A `frames` result holds at most 1,000 frames, 1,000 table rows in total, and 100,000 values in total; a `samples` result holds at most 1,000 samples. The request body is limited to 256 KiB and the whole success response to 10 MiB.\n- Failures use the standard error envelope. `error.reason` is a stable machine-readable value; a data source ID that does not exist returns HTTP 400 with code `ResourceNotFound` and no `reason`.\n- Query execution may take up to 35 seconds across WebAPI forwarding and Edge execution. Configure client timeouts to at least 40 seconds.", - "href": "/en/api-reference/monitors/diagnostics/monit-read-query-explore", - "metadata": { - "sidebarTitle": "Run Explore query" - } - } - } - }, - "/monit/query/data": { - "post": { - "operationId": "monit-read-query-data", - "summary": "Query structured data", - "description": "Run a synchronous ad-hoc query against a data source and return a `query_result.v1` result as frames, records, or samples.", - "tags": [ - "Monitors/Diagnostics" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **5 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n| Edge requirement | Supported deployments require **monit-edge v0.65.0 or later** |\n\n## Usage\n\n- The data source is identified by `ds_type` plus `ds_name`, not by ID. It must belong to the account and be enabled. When the data source restricts querying to certain teams, only members of those teams, its managing team, and account owners or admins can query it; others get `AccessDenied`.\n- Treat **monit-edge v0.65.0** as the minimum supported Edge version for this public API. WebAPI retains migration adapters for older Edge versions: query.v2 results may still preserve frames, records, or samples, while legacy rows can expose only the information they retained. These adapters do not change the support floor; older protocols lack query.v3 cancellation and error-lifecycle semantics, and data already lost by legacy rows cannot be recovered.\n- The public response format is always `query_result.v1` and is independent of the internal Edge query protocol. Dispatch on `result.kind` (`frames`, `records`, or `samples`); do not infer the result shape from `ds_type` or the Edge version.\n- A `frames` result may contain multiple table or time-series frames. Field values are columnar and all fields in one frame have the same length.\n- A `records` result may contain nested JSON and null records. Integer literals outside JavaScript's safe integer range are returned as decimal strings.\n- A `samples` result contains label sets and instant values. A value may be a number or one of the strings `NaN`, `+Inf`, and `-Inf`.\n- Prometheus expressions are syntax-checked before the query is dispatched; an invalid expression returns HTTP 400.\n- The request body is limited to 256 KiB and the complete success response to 10 MiB; either limit returns HTTP 413. A result with more than 1,000 rows fails with HTTP 400. Narrow the time range, reduce fields, or aggregate at the source.\n- Query failures use non-2xx HTTP status codes and the standard error envelope.\n- Query execution may take up to 35 seconds across WebAPI forwarding and Edge execution. Configure client timeouts to at least 40 seconds and propagate cancellation when the caller abandons a query.", - "href": "/en/api-reference/monitors/diagnostics/monit-read-query-data", - "metadata": { - "sidebarTitle": "Query structured data" + "$ref": "#/components/responses/ServerError" } }, "requestBody": { @@ -49517,17 +52045,37 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/QueryDataRequest" + "$ref": "#/components/schemas/RuleFieldsUpdateRequest" }, "example": { - "ds_type": "prometheus", - "ds_name": "prod-prom", - "expr": "sum by (job) (rate(http_requests_total[5m]))", - "delay_seconds": 0, - "args": {} + "ids": [ + 50001, + 50002 + ], + "fields": [ + "enabled" + ], + "enabled": false } } } + } + } + }, + "/monit/rule/v2/info": { + "post": { + "operationId": "monit-rule-read-info-v2", + "summary": "Get alert rule detail (V2)", + "description": "Return the full V2 configuration of an alert rule by ID, including lifecycle v2 recovery and ending modes.", + "tags": [ + "Monitors/Alert rules" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Alerting Rules Read** or **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `id` is required and must not be `0`; otherwise the call returns `InvalidParameter`.\n- A missing rule, or a rule of another account, returns `InvalidParameter` (`alert rule not found`).\n- The caller must have access to the rule's folder (the account owner or an admin, the creator of the folder or an ancestor, or a member of the team bound to it or an ancestor); otherwise the call returns `AccessDenied`. A rule whose folder no longer exists returns `InvalidParameter` (folder not found).", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-info-v2", + "metadata": { + "sidebarTitle": "Get alert rule detail (V2)" + } }, "responses": { "200": { @@ -49543,7 +52091,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/QueryDataResponse" + "$ref": "#/components/schemas/AlertRuleV2" } } } @@ -49552,18 +52100,69 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "format": "query_result.v1", - "result": { - "kind": "samples", - "samples": [ + "id": 50001, + "account_id": 888, + "folder_id": 100, + "name": "CPU High", + "labels": {}, + "ds_type": "prometheus", + "ds_list": [ + "prometheus*" + ], + "ds_ids": [], + "enabled": true, + "debug_log_enabled": false, + "rule_configs": { + "relate_queries": [], + "queries": [ { - "labels": { - "job": "api" - }, - "value": 1.25 + "name": "A", + "expr": "100 - avg(cpu_usage_idle)" } - ] - } + ], + "check_threshold": { + "enabled": true, + "alerting_check_times": 3, + "alerting_window_size": 5, + "recovery_check_times": 2, + "critical": "$A > 90", + "warning": "$A > 80", + "recovery_mode": "condition_clear" + } + }, + "cron_pattern": "0 * * * * *", + "timezone": "Asia/Shanghai", + "delay_seconds": 0, + "enabled_times": [ + { + "days": [ + 1, + 2, + 3, + 4, + 5, + 6, + 0 + ], + "stime": "00:00", + "etime": "23:59" + } + ], + "annotations": {}, + "description_type": "text", + "description": "", + "channel_ids": [ + 20001 + ], + "repeat_interval": 3600, + "repeat_total": 3, + "investigation_targets": [], + "creator_id": 66, + "creator_name": "zhangsan", + "updater_id": 66, + "updater_name": "zhangsan", + "created_at": 1712000000, + "updated_at": 1712000000 } } } @@ -49578,61 +52177,41 @@ "403": { "$ref": "#/components/responses/Forbidden" }, - "413": { - "description": "The request or final response exceeds its size limit.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, "429": { "$ref": "#/components/responses/TooManyRequests" }, - "499": { - "description": "The client canceled the query.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, "500": { "$ref": "#/components/responses/ServerError" - }, - "503": { - "$ref": "#/components/responses/ServiceUnavailable" - }, - "504": { - "description": "The query timed out.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RuleIDRequest" + }, + "example": { + "id": 50001 } } } } } }, - "/monit/rule/audit/detail": { + "/monit/rule/v2/create": { "post": { - "operationId": "monit-rule-read-audit-detail", - "summary": "Get rule audit snapshot", - "description": "Return one audit record of an alert rule, including the rule snapshot stored in `content`.", + "operationId": "monit-rule-write-create-v2", + "summary": "Create alert rule (V2)", + "description": "Create a new V2 alert rule. Returns the created rule with its assigned ID.", "tags": [ "Monitors/Alert rules" ], "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- Pass the audit record `id` (not the rule `id`) from `POST /monit/rule/audits`. An unknown ID returns `InvalidParameter` (`alert rule audit not found`).\n- `content` is a JSON string — parse it to get the rule snapshot; its shape depends on the operation that wrote the record (see `content` below).\n- To read a record, the caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`. Records of a deleted rule can no longer be read: the call returns `InvalidParameter` (`alert rule not found`).", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-audit-detail", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `folder_id`, `name`, `ds_type`, `enabled`, `cron_pattern` and `rule_configs.queries` are required, and at least one of `ds_list` (wildcards supported) or `ds_ids` must be non-empty.\n- `enabled` must be passed explicitly (including `false`); omitting it returns `InvalidParameter`.\n- `folder_id` must be an existing folder (otherwise `InvalidParameter`) and the caller must be able to manage the folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor) (otherwise `AccessDenied`).\n- `name` must be unique within `folder_id`; a duplicate returns `InvalidParameter`.\n- When `enabled` is `true`, `ds_type` must be a datasource type that supports alerting and every ID in `ds_ids` must be an enabled datasource with alerting turned on; otherwise the call returns `InvalidParameter`.\n- Callers other than the account owner or admins need read-only access to every datasource listed in `ds_ids` or currently matched by `ds_list`; otherwise the call returns `AccessDenied` (`no permission to reference datasource \"\"`).\n- The call fails with `AccessDenied` when creating the rule would exceed the account's alert rule license limit.\n- `id`, `account_id`, `creator_*`, `updater_*`, `created_at`, and `updated_at` are assigned by the server; client-supplied values are ignored.\n- `channel_ids` can be empty; alerts will then route through the global integration.\n- The request body may not exceed 1 MiB; a larger body returns HTTP 413 (`EntityTooLarge`). Additional unknown fields are ignored (forward compatibility).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-create-v2", "metadata": { - "sidebarTitle": "Get rule audit snapshot" + "sidebarTitle": "Create alert rule (V2)" } }, "responses": { @@ -49649,7 +52228,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertRuleAudit" + "$ref": "#/components/schemas/AlertRuleV2" } } } @@ -49658,14 +52237,69 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "id": 9001, + "id": 50001, "account_id": 888, - "alert_rule_id": 50001, - "action": "update", - "content": "{\"id\":50001,\"account_id\":888,\"folder_id\":100,\"name\":\"CPU High\",\"enabled\":true,\"updated_at\":1712003600}", + "folder_id": 100, + "name": "CPU High", + "labels": {}, + "ds_type": "prometheus", + "ds_list": [ + "prometheus*" + ], + "ds_ids": [], + "enabled": true, + "debug_log_enabled": false, + "rule_configs": { + "relate_queries": [], + "queries": [ + { + "name": "A", + "expr": "100 - avg(cpu_usage_idle)" + } + ], + "check_threshold": { + "enabled": true, + "alerting_check_times": 3, + "alerting_window_size": 5, + "recovery_check_times": 2, + "critical": "$A > 90", + "warning": "$A > 80", + "recovery_mode": "condition_clear" + } + }, + "cron_pattern": "0 * * * * *", + "timezone": "Asia/Shanghai", + "delay_seconds": 0, + "enabled_times": [ + { + "days": [ + 1, + 2, + 3, + 4, + 5, + 6, + 0 + ], + "stime": "00:00", + "etime": "23:59" + } + ], + "annotations": {}, + "description_type": "text", + "description": "", + "channel_ids": [ + 20001 + ], + "repeat_interval": 3600, + "repeat_total": 3, + "investigation_targets": [], "creator_id": 66, "creator_name": "zhangsan", - "created_at": 1712003600 + "updater_id": 66, + "updater_name": "zhangsan", + "created_at": 1712000000, + "updated_at": 1712000000 } } } @@ -49692,29 +52326,56 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AuditRecordIDRequest" + "$ref": "#/components/schemas/AlertRuleV2" }, "example": { - "id": 9001 + "folder_id": 100, + "name": "CPU High", + "ds_type": "prometheus", + "ds_list": [ + "prometheus*" + ], + "enabled": true, + "cron_pattern": "0 * * * * *", + "channel_ids": [ + 20001 + ], + "rule_configs": { + "queries": [ + { + "name": "A", + "expr": "100 - avg(cpu_usage_idle)" + } + ], + "check_threshold": { + "enabled": true, + "alerting_check_times": 3, + "alerting_window_size": 5, + "recovery_check_times": 2, + "critical": "$A > 90", + "warning": "$A > 80", + "recovery_mode": "condition_clear" + } + } } } } } } }, - "/monit/rule/audits": { + "/monit/rule/v2/update": { "post": { - "operationId": "monit-rule-read-audits", - "summary": "List rule change history", - "description": "Return the change history (audit records) for an alert rule.", + "operationId": "monit-rule-write-update-v2", + "summary": "Update alert rule (V2)", + "description": "Replace an alert rule's V2 configuration in full by ID. Returns the updated rule.", "tags": [ "Monitors/Alert rules" ], "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- Records are ordered newest first and omit `content`; read one snapshot with `POST /monit/rule/audit/detail`.\n- A record is written on every create, full update, field update and move. Deleting a rule writes no record, and the history of a deleted rule can no longer be listed: the call returns `InvalidParameter` (`alert rule not found`).\n- The caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-audits", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `id` is required and the rule must already exist; otherwise the call returns `InvalidParameter`.\n- This is a full-field replacement: except for the cases below, fields you omit are stored as zero values (then normalized, e.g. `repeat_interval` becomes 3600). Fetch the full configuration via `/monit/rule/v2/info` before modifying it.\n- `enabled` must be passed explicitly (including `false`); omitting it returns `InvalidParameter`. Setting it to `false` clears the rule's active alerts.\n- `investigation_targets` is the exception: omit it to keep the current value, pass `[]` to clear, or pass a value to replace it entirely.\n- `folder_id` cannot be changed through this operation; use `/monit/rule/move` to move the rule to another folder.\n- The caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.\n- `name` must be unique within the rule's folder; a duplicate returns `InvalidParameter`.\n- When `enabled` is `true`, `ds_type` must be a datasource type that supports alerting and every ID in `ds_ids` must be an enabled datasource with alerting turned on; otherwise the call returns `InvalidParameter`.\n- Callers other than the account owner or admins need read-only access to every datasource listed in `ds_ids` or currently matched by `ds_list`; otherwise the call returns `AccessDenied` (`no permission to reference datasource \"\"`).\n- The call fails with `AccessDenied` when the account already exceeds its alert rule license limit.\n- If the rule is modified by another request while this one is processed, the call returns HTTP 409 (`UndonedOrderExist`, `alert rule was modified; reload and retry`); fetch the rule again and retry.\n- `account_id`, `creator_*`, `updater_*`, `created_at`, and `updated_at` are maintained by the server; client-supplied values are ignored.\n- The request body may not exceed 1 MiB; a larger body returns HTTP 413 (`EntityTooLarge`). Additional unknown fields are ignored (forward compatibility).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-update-v2", "metadata": { - "sidebarTitle": "List rule change history" + "sidebarTitle": "Update alert rule (V2)" } }, "responses": { @@ -49731,7 +52392,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleAuditListResponse" + "$ref": "#/components/schemas/AlertRuleV2" } } } @@ -49739,26 +52400,71 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": [ - { - "id": 9001, - "account_id": 888, - "alert_rule_id": 50001, - "action": "update", - "creator_id": 66, - "creator_name": "zhangsan", - "created_at": 1712003600 - }, - { - "id": 8990, - "account_id": 888, - "alert_rule_id": 50001, - "action": "create", - "creator_id": 66, - "creator_name": "zhangsan", - "created_at": 1712000000 - } - ] + "data": { + "id": 50001, + "account_id": 888, + "folder_id": 100, + "name": "CPU High", + "labels": {}, + "ds_type": "prometheus", + "ds_list": [ + "prometheus*" + ], + "ds_ids": [], + "enabled": true, + "debug_log_enabled": false, + "rule_configs": { + "relate_queries": [], + "queries": [ + { + "name": "A", + "expr": "100 - avg(cpu_usage_idle)" + } + ], + "check_threshold": { + "enabled": true, + "alerting_check_times": 3, + "alerting_window_size": 5, + "recovery_check_times": 2, + "critical": "$A > 95", + "warning": "$A > 80", + "recovery_mode": "condition_clear" + } + }, + "cron_pattern": "0 * * * * *", + "timezone": "Asia/Shanghai", + "delay_seconds": 0, + "enabled_times": [ + { + "days": [ + 1, + 2, + 3, + 4, + 5, + 6, + 0 + ], + "stime": "00:00", + "etime": "23:59" + } + ], + "annotations": {}, + "description_type": "text", + "description": "", + "channel_ids": [ + 20001 + ], + "repeat_interval": 3600, + "repeat_total": 3, + "investigation_targets": [], + "creator_id": 66, + "creator_name": "zhangsan", + "updater_id": 66, + "updater_name": "zhangsan", + "created_at": 1712000000, + "updated_at": 1712003600 + } } } } @@ -49784,9 +52490,37 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleIDRequest" + "$ref": "#/components/schemas/AlertRuleV2" }, "example": { + "folder_id": 100, + "name": "CPU High", + "ds_type": "prometheus", + "ds_list": [ + "prometheus*" + ], + "enabled": true, + "cron_pattern": "0 * * * * *", + "channel_ids": [ + 20001 + ], + "rule_configs": { + "queries": [ + { + "name": "A", + "expr": "100 - avg(cpu_usage_idle)" + } + ], + "check_threshold": { + "enabled": true, + "alerting_check_times": 3, + "alerting_window_size": 5, + "recovery_check_times": 2, + "critical": "$A > 95", + "warning": "$A > 80", + "recovery_mode": "condition_clear" + } + }, "id": 50001 } } @@ -49794,19 +52528,19 @@ } } }, - "/monit/rule/counter/channel": { + "/oncall/license/list": { "post": { - "operationId": "monit-rule-read-counter-channel", - "summary": "Get rule counts by channel", - "description": "Return how many alert rules route alerts to each collaboration space, keyed by space name.", + "operationId": "oncall-license-read-license-list", + "summary": "List On-call licenses", + "description": "List people with active fixed or temporary On-call licenses in the current account.", "tags": [ - "Monitors/Alert rules" + "On-call/Licenses" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Monits Overview Read** (`monit`) |\n\n## Usage\n\n- Only rules with a non-empty `channel_ids` are counted; a rule routed to several spaces is counted once under each of them.\n- When a space ID cannot be resolved to a name, the ID (as a string) is used as the key. Spaces that share the same name are merged into one key.\n- Returns an empty object `{}` when no rule routes to a space.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-counter-channel", + "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- `items` contains only people with an active fixed or temporary On-call license.\n- For temporary licenses, `updated_by`, `created_at`, and `updated_at` are `0`.", + "href": "/en/api-reference/on-call/licenses/oncall-license-read-license-list", "metadata": { - "sidebarTitle": "Get rule counts by channel" + "sidebarTitle": "List On-call licenses" } }, "responses": { @@ -49823,16 +52557,35 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCounterChannelResponse" + "$ref": "#/components/schemas/LicenseListResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "request_id": "01J0D5Y31GY2TWAHRP3Q8K4M6N", "data": { - "Production": 8 + "total": 2, + "items": [ + { + "person_id": 80011, + "person_name": "Yuki Zhang", + "type": "fixed", + "updated_by": 80001, + "created_at": 1719792000, + "updated_at": 1719878400 + }, + { + "person_id": 80012, + "person_name": "Alex Chen", + "type": "temporary", + "updated_by": 0, + "created_at": 0, + "updated_at": 0 + } + ], + "release_limited": false } } } @@ -49859,7 +52612,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleEmptyRequest" + "$ref": "#/components/schemas/EmptyRequest" }, "example": {} } @@ -49867,19 +52620,19 @@ } } }, - "/monit/rule/counter/total": { + "/person/infos": { "post": { - "operationId": "monit-rule-read-counter-total", - "summary": "Get rule counter time series", - "description": "Return the stored time series of the total rule count across the account — one sample per `clock` timestamp.", + "operationId": "personInfos", + "summary": "Batch get persons", + "description": "Return profile information for a batch of person IDs (members or accounts).", "tags": [ - "Monitors/Alert rules" + "Platform/Members" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Monits Overview Read** (`monit`) |\n\n## Usage\n\n- Each item is a historical snapshot: `num` is the total number of alert rules in the account (enabled and disabled) at `clock` (Unix timestamp in seconds).\n- A snapshot is recorded roughly every 12 hours (an hourly job adds one when none exists in the last 12 hours). All snapshots are returned oldest first; the array is empty until the first snapshot is recorded.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-counter-total", + "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- Including the account ID returns the account owner, with `as` `account`. Other IDs are looked up among the account's members, including removed ones (`status` `deleted`), so IDs saved in older records still resolve.\n- Duplicate IDs are deduplicated; IDs that match neither are omitted.", + "href": "/en/api-reference/platform/members/person-infos", "metadata": { - "sidebarTitle": "Get rule counter time series" + "sidebarTitle": "Batch get persons" } }, "responses": { @@ -49896,7 +52649,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCounterTotalResponse" + "$ref": "#/components/schemas/PersonInfosResponse" } } } @@ -49904,20 +52657,33 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": [ - { - "id": 1, - "account_id": 888, - "num": 48, - "clock": 1711956000 - }, - { - "id": 2, - "account_id": 888, - "num": 50, - "clock": 1712000000 - } - ] + "data": { + "items": [ + { + "account_id": 2451002751131, + "person_id": 2476444212131, + "person_name": "Alice", + "avatar": "/image/avatar1.png", + "locale": "zh-CN", + "time_zone": "Asia/Shanghai", + "email": "alice@example.com", + "phone_verified": false, + "email_verified": true, + "as": "member", + "status": "enabled" + }, + { + "account_id": 2451002751131, + "person_id": 3790925372131, + "person_name": "Bob", + "email": "bob@example.com", + "phone_verified": false, + "email_verified": true, + "as": "member", + "status": "enabled" + } + ] + } } } } @@ -49943,27 +52709,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleEmptyRequest" + "$ref": "#/components/schemas/PersonInfosRequest" }, - "example": {} + "example": { + "person_ids": [ + 2476444212131, + 3790925372131 + ] + } } } } } }, - "/monit/rule/delete": { + "/role/delete": { "post": { - "operationId": "monit-rule-write-delete", - "summary": "Delete alert rule", - "description": "Delete a single alert rule by its ID.", + "operationId": "role-write-delete", + "summary": "Delete a role", + "description": "Delete a custom role, optionally revoking it from every member who still holds it.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- The rule's active alerts are cleared as part of the deletion.\n- Deleting an ID that does not exist succeeds with an empty `data`, so retries are safe.\n- The caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-delete", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- While members still hold the role, the call fails with `400 ReferenceExist` and lists them in `data.refs` (`kind` `member`); set `is_force` to `true` to revoke the role from all of them and then delete it.\n- A role selected as a default role in the SSO configuration cannot be deleted, even with `is_force`; the call fails with `400 ReferenceExist` until it is unselected there.\n- A role ID that does not exist or was already deleted is ignored and the call succeeds.\n- The built-in roles (`2`, `6`, `8`) cannot be deleted: with or without `is_force`, the call returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/roles-permissions/role-write-delete", "metadata": { - "sidebarTitle": "Delete alert rule" + "sidebarTitle": "Delete a role" } }, "responses": { @@ -49980,7 +52751,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleEmptyResponse" + "$ref": "#/components/schemas/PlatformEmptyObject" } } } @@ -50014,29 +52785,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleIDRequest" + "$ref": "#/components/schemas/RoleDeleteRequest" }, "example": { - "id": 50001 + "role_id": 150 } } } } } }, - "/monit/rule/delete/batch": { + "/role/disable": { "post": { - "operationId": "monit-rule-write-delete-batch", - "summary": "Batch delete alert rules", - "description": "Delete multiple alert rules in a single request.", + "operationId": "role-write-disable", + "summary": "Disable a role", + "description": "Set a custom role's status to disabled without deleting it.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **5 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- IDs are processed in order and the call stops at the first error; rules deleted before the error stay deleted, so fix the cause and re-send the remaining IDs.\n- IDs that do not exist are skipped without error. Each deleted rule's active alerts are cleared.\n- `ids` must contain at least one ID. For every rule, the caller must be able to manage its folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-delete-batch", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Only a role in `enabled` status can be disabled; calling it on a role that is already disabled returns `400 InvalidParameter`.\n- The built-in roles (`2`, `6`, `8`) cannot be disabled: the call returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- A role ID that does not exist or was deleted is ignored and the call succeeds.\n- Disabling does not revoke the role from the members who hold it, but a disabled role grants no permissions: those members, and the app keys they created, lose the role's permissions until it is enabled again.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/roles-permissions/role-write-disable", "metadata": { - "sidebarTitle": "Batch delete alert rules" + "sidebarTitle": "Disable a role" } }, "responses": { @@ -50053,7 +52824,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleEmptyResponse" + "$ref": "#/components/schemas/PlatformEmptyObject" } } } @@ -50087,32 +52858,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleIDsRequest" + "$ref": "#/components/schemas/RoleIDRequest" }, "example": { - "ids": [ - 50001, - 50002 - ] + "role_id": 150 } } } } } }, - "/monit/rule/list/basic": { + "/role/enable": { "post": { - "operationId": "monit-rule-read-list", - "summary": "List alert rules", - "description": "Return basic information for the alert rules in a folder; call `POST /monit/rule/v2/info` for full details.", + "operationId": "role-write-enable", + "summary": "Enable a role", + "description": "Re-enable a previously disabled custom role.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Alerting Rules Read** or **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `folder_id` must be an existing folder: `0` or an unknown ID returns `InvalidParameter`, and a folder the caller cannot manage (account owner or admin, creator of the folder or an ancestor, or member of the team bound to it or an ancestor) returns `AccessDenied`. There is no account-wide listing.\n- By default only the rules directly in the folder are returned, sorted by name, with `active_alert_count` and `runtime_state` filled.\n- With `include_descendants: true` the call searches the folder and all its descendant folders and returns at most `limit` rules sorted by name; only `id`, `folder_id` and `name` are filled and the other fields carry zero values (`labels` is `null`, `runtime_state` is omitted).\n- `triggered` is `true` exactly when `active_alert_count > 0`.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Only a role in `disabled` status can be enabled; calling it on an enabled role returns `400 InvalidParameter`.\n- The built-in roles (`2`, `6`, `8`) cannot be enabled or disabled: the call returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- Once enabled, the role's permissions apply again to the members who hold it and to the app keys those members created.\n- A role ID that does not exist or was deleted is ignored and the call succeeds.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/roles-permissions/role-write-enable", "metadata": { - "sidebarTitle": "List alert rules" + "sidebarTitle": "Enable a role" } }, "responses": { @@ -50129,7 +52897,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleBasicListResponse" + "$ref": "#/components/schemas/PlatformEmptyObject" } } } @@ -50137,32 +52905,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": [ - { - "id": 50001, - "account_id": 888, - "folder_id": 100, - "name": "CPU High", - "labels": { - "team": "sre" - }, - "ds_type": "prometheus", - "enabled": true, - "debug_log_enabled": false, - "cron_pattern": "0 * * * * *", - "timezone": "Asia/Shanghai", - "delay_seconds": 0, - "creator_id": 66, - "creator_name": "zhangsan", - "updater_id": 66, - "updater_name": "zhangsan", - "created_at": 1710000000, - "updated_at": 1712000000, - "triggered": true, - "active_alert_count": 2, - "runtime_state": "normal" - } - ] + "data": {} } } } @@ -50188,29 +52931,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleListRequest" + "$ref": "#/components/schemas/RoleIDRequest" }, "example": { - "folder_id": 100 + "role_id": 150 } } } } } }, - "/monit/rule/move": { + "/role/info": { "post": { - "operationId": "monit-rule-write-move", - "summary": "Move alert rules to folder", - "description": "Move one or more alert rules to a different folder.", + "operationId": "role-read-info", + "summary": "Get role detail", + "description": "Return the detail of a single role by its ID.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `dest_folder_id` must be an existing folder that the caller must be able to manage the folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the whole call fails with `AccessDenied` and nothing is moved.\n- The result has one entry per requested ID, in request order. A moved rule's `message` is a localized success text (`Move successfully` / `移动成功`); a rule that is not moved stays in its folder and its `message` carries the error.\n- A rule is not moved when a rule with the same name already exists in the destination folder, when the caller cannot manage its current folder, or when the ID does not exist (its `name` is then `id: `).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-move", + "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 `2`, `6`, and `8` return the built-in Admin, Responder, and Viewer roles; their `description` follows the request language.\n- A role ID that does not exist or was deleted returns `400 InvalidParameter`.", + "href": "/en/api-reference/platform/roles-permissions/role-read-info", "metadata": { - "sidebarTitle": "Move alert rules to folder" + "sidebarTitle": "Get role detail" } }, "responses": { @@ -50227,7 +52970,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleNameMessageListResponse" + "$ref": "#/components/schemas/RoleItem" } } } @@ -50235,16 +52978,21 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": [ - { - "name": "CPU High", - "message": "Move successfully" - }, - { - "name": "Disk High", - "message": "alert rule name already exists in this folder" - } - ] + "data": { + "role_id": 2, + "role_name": "Admin", + "description": "Account Administrator, has all account permissions and can assist the main account in managing all affairs.", + "status": "enabled", + "permission_ids": [ + 101, + 102, + 201, + 701 + ], + "editable": false, + "created_at": 1653530940, + "updated_at": 1653530940 + } } } } @@ -50270,33 +53018,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleMoveRequest" + "$ref": "#/components/schemas/RoleInfoRequest" }, "example": { - "ids": [ - 50001, - 50002 - ], - "dest_folder_id": 200 + "role_id": 2 } } } } } }, - "/monit/rule/update/fields": { + "/role/list": { "post": { - "operationId": "monit-rule-write-fields-update", - "summary": "Batch update rule fields", - "description": "Update the fields listed in `fields` on multiple alert rules in one call.", + "operationId": "role-read-list", + "summary": "List roles", + "description": "Return all custom and built-in roles for the current account.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- Each listed field takes the value of the same-named request field; a listed field whose value is omitted is set to its zero value (for example, listing `labels` without `labels` or `labels_patch` removes all labels). Unlisted fields keep their current values.\n- An unknown name in `fields`, a `labels_patch` / `annotations_patch` whose field is not listed in `fields`, or sending `labels` together with `labels_patch` (or `annotations` with `annotations_patch`) fails the whole call with `InvalidParameter`.\n- Rules are updated one by one and the result has one entry per ID: `message` is empty on success, otherwise it carries that rule's error (validation failure, no access to its folder, or an unknown ID, whose `name` is then `id: `).\n- Setting `enabled` to `false` clears the rules' active alerts. Unless the call only disables rules (`fields` is exactly `[\"enabled\"]` with `enabled: false`), it fails with `AccessDenied` when the account exceeds its alert rule license limit, and non-admin callers need read-only access to every datasource each rule selects.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-fields-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- Custom roles (enabled and disabled) come first, sorted by `orderby`/`asc`; the three built-in roles — `2` Admin, `6` Responder, `8` Viewer — are appended at the end unless `no_global` is true, and are counted in `total`.\n- Built-in roles have `editable: false`, and their `description` follows the request language (`Accept-Language` header, or the `locale`/`lang` query parameter).", + "href": "/en/api-reference/platform/roles-permissions/role-read-list", "metadata": { - "sidebarTitle": "Batch update rule fields" + "sidebarTitle": "List roles" } }, "responses": { @@ -50313,7 +53057,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleNameMessageListResponse" + "$ref": "#/components/schemas/RoleListResponse" } } } @@ -50321,16 +53065,64 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": [ - { - "name": "CPU High", - "message": "" - }, - { - "name": "Disk High", - "message": "" - } - ] + "data": { + "total": 4, + "items": [ + { + "role_id": 150, + "role_name": "On-call Manager", + "description": "Manage on-call rotations and incidents.", + "status": "enabled", + "permission_ids": [ + 501, + 502 + ], + "editable": true, + "created_at": 1710000000, + "updated_at": 1712000000 + }, + { + "role_id": 2, + "role_name": "Admin", + "description": "Account Administrator, has all account permissions and can assist the main account in managing all affairs.", + "status": "enabled", + "permission_ids": [ + 101, + 102, + 201, + 701 + ], + "editable": false, + "created_at": 1653530940, + "updated_at": 1653530940 + }, + { + "role_id": 6, + "role_name": "Responder", + "description": "Responder, has standard permissions except billing center, member management, role management and single sign-on management, suitable for members handling daily operations.", + "status": "enabled", + "permission_ids": [ + 201, + 701 + ], + "editable": false, + "created_at": 1653530940, + "updated_at": 1653530940 + }, + { + "role_id": 8, + "role_name": "Viewer", + "description": "Viewer, has most read-only permissions except audit and onboarding, suitable for members who only need to view data.", + "status": "enabled", + "permission_ids": [ + 103 + ], + "editable": false, + "created_at": 1653530940, + "updated_at": 1653530940 + } + ] + } } } } @@ -50356,125 +53148,55 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleFieldsUpdateRequest" + "$ref": "#/components/schemas/RoleListRequest" }, "example": { - "ids": [ - 50001, - 50002 - ], - "fields": [ - "enabled" - ], - "enabled": false + "orderby": "created_at", + "asc": false } } } } } }, - "/monit/rule/v2/info": { + "/role/member/grant": { "post": { - "operationId": "monit-rule-read-info-v2", - "summary": "Get alert rule detail (V2)", - "description": "Return the full V2 configuration of an alert rule by ID, including lifecycle v2 recovery and ending modes.", + "operationId": "role-write-grant-role", + "summary": "Grant role to members", + "description": "Assign a role to one or more members, giving them its permissions.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Alerting Rules Read** or **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `id` is required and must not be `0`; otherwise the call returns `InvalidParameter`.\n- A missing rule, or a rule of another account, returns `InvalidParameter` (`alert rule not found`).\n- The caller must have access to the rule's folder (the account owner or an admin, the creator of the folder or an ancestor, or a member of the team bound to it or an ancestor); otherwise the call returns `AccessDenied`. A rule whose folder no longer exists returns `InvalidParameter` (folder not found).", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-read-info-v2", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Every ID in `member_ids` must be a member of the account, with no duplicates; otherwise the call returns `400` and nobody is changed.\n- `role_id` must be a built-in role or a custom role that has not been deleted (disabled roles are accepted, but grant no permissions until enabled); otherwise the call returns `400`.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Members who already hold the role keep it unchanged.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/roles-permissions/role-write-grant-role", "metadata": { - "sidebarTitle": "Get alert rule detail (V2)" + "sidebarTitle": "Grant role to members" } }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "type": "object", - "properties": { - "data": { - "$ref": "#/components/schemas/AlertRuleV2" - } - } - } - ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "id": 50001, - "account_id": 888, - "folder_id": 100, - "name": "CPU High", - "labels": {}, - "ds_type": "prometheus", - "ds_list": [ - "prometheus*" - ], - "ds_ids": [], - "enabled": true, - "debug_log_enabled": false, - "rule_configs": { - "relate_queries": [], - "queries": [ - { - "name": "A", - "expr": "100 - avg(cpu_usage_idle)" - } - ], - "check_threshold": { - "enabled": true, - "alerting_check_times": 3, - "alerting_window_size": 5, - "recovery_check_times": 2, - "critical": "$A > 90", - "warning": "$A > 80", - "recovery_mode": "condition_clear" - } - }, - "cron_pattern": "0 * * * * *", - "timezone": "Asia/Shanghai", - "delay_seconds": 0, - "enabled_times": [ - { - "days": [ - 1, - 2, - 3, - 4, - 5, - 6, - 0 - ], - "stime": "00:00", - "etime": "23:59" + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/PlatformEmptyObject" + } } - ], - "annotations": {}, - "description_type": "text", - "description": "", - "channel_ids": [ - 20001 - ], - "repeat_interval": 3600, - "repeat_total": 3, - "investigation_targets": [], - "creator_id": 66, - "creator_name": "zhangsan", - "updater_id": 66, - "updater_name": "zhangsan", - "created_at": 1712000000, - "updated_at": 1712000000 - } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } } @@ -50500,29 +53222,33 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RuleIDRequest" + "$ref": "#/components/schemas/RoleGrantRequest" }, "example": { - "id": 50001 + "member_ids": [ + 80011, + 80012 + ], + "role_id": 150 } } } } } }, - "/monit/rule/v2/create": { + "/role/member/revoke": { "post": { - "operationId": "monit-rule-write-create-v2", - "summary": "Create alert rule (V2)", - "description": "Create a new V2 alert rule. Returns the created rule with its assigned ID.", + "operationId": "role-write-revoke-role", + "summary": "Revoke role from members", + "description": "Remove a role from one or more members, revoking the permissions it granted.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `folder_id`, `name`, `ds_type`, `enabled`, `cron_pattern` and `rule_configs.queries` are required, and at least one of `ds_list` (wildcards supported) or `ds_ids` must be non-empty.\n- `enabled` must be passed explicitly (including `false`); omitting it returns `InvalidParameter`.\n- `folder_id` must be an existing folder (otherwise `InvalidParameter`) and the caller must be able to manage the folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor) (otherwise `AccessDenied`).\n- `name` must be unique within `folder_id`; a duplicate returns `InvalidParameter`.\n- When `enabled` is `true`, `ds_type` must be a datasource type that supports alerting and every ID in `ds_ids` must be an enabled datasource with alerting turned on; otherwise the call returns `InvalidParameter`.\n- Callers other than the account owner or admins need read-only access to every datasource listed in `ds_ids` or currently matched by `ds_list`; otherwise the call returns `AccessDenied` (`no permission to reference datasource \"\"`).\n- The call fails with `AccessDenied` when creating the rule would exceed the account's alert rule license limit.\n- `id`, `account_id`, `creator_*`, `updater_*`, `created_at`, and `updated_at` are assigned by the server; client-supplied values are ignored.\n- `channel_ids` can be empty; alerts will then route through the global integration.\n- The request body may not exceed 1 MiB; a larger body returns HTTP 413 (`EntityTooLarge`). Additional unknown fields are ignored (forward compatibility).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-create-v2", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Every ID in `member_ids` must be a member of the account, with no duplicates; otherwise the call returns `400` and nobody is changed.\n- `role_id` must be a built-in role or a custom role that has not been deleted (disabled roles are accepted); otherwise the call returns `400`.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Members who don't hold the role are left unchanged; revoking a member's last role leaves them with no roles.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/roles-permissions/role-write-revoke-role", "metadata": { - "sidebarTitle": "Create alert rule (V2)" + "sidebarTitle": "Revoke role from members" } }, "responses": { @@ -50539,7 +53265,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertRuleV2" + "$ref": "#/components/schemas/PlatformEmptyObject" } } } @@ -50547,71 +53273,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "id": 50001, - "account_id": 888, - "folder_id": 100, - "name": "CPU High", - "labels": {}, - "ds_type": "prometheus", - "ds_list": [ - "prometheus*" - ], - "ds_ids": [], - "enabled": true, - "debug_log_enabled": false, - "rule_configs": { - "relate_queries": [], - "queries": [ - { - "name": "A", - "expr": "100 - avg(cpu_usage_idle)" - } - ], - "check_threshold": { - "enabled": true, - "alerting_check_times": 3, - "alerting_window_size": 5, - "recovery_check_times": 2, - "critical": "$A > 90", - "warning": "$A > 80", - "recovery_mode": "condition_clear" - } - }, - "cron_pattern": "0 * * * * *", - "timezone": "Asia/Shanghai", - "delay_seconds": 0, - "enabled_times": [ - { - "days": [ - 1, - 2, - 3, - 4, - 5, - 6, - 0 - ], - "stime": "00:00", - "etime": "23:59" - } - ], - "annotations": {}, - "description_type": "text", - "description": "", - "channel_ids": [ - 20001 - ], - "repeat_interval": 3600, - "repeat_total": 3, - "investigation_targets": [], - "creator_id": 66, - "creator_name": "zhangsan", - "updater_id": 66, - "updater_name": "zhangsan", - "created_at": 1712000000, - "updated_at": 1712000000 - } + "data": {} } } } @@ -50637,56 +53299,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertRuleV2" + "$ref": "#/components/schemas/RoleGrantRequest" }, "example": { - "folder_id": 100, - "name": "CPU High", - "ds_type": "prometheus", - "ds_list": [ - "prometheus*" - ], - "enabled": true, - "cron_pattern": "0 * * * * *", - "channel_ids": [ - 20001 + "member_ids": [ + 80011 ], - "rule_configs": { - "queries": [ - { - "name": "A", - "expr": "100 - avg(cpu_usage_idle)" - } - ], - "check_threshold": { - "enabled": true, - "alerting_check_times": 3, - "alerting_window_size": 5, - "recovery_check_times": 2, - "critical": "$A > 90", - "warning": "$A > 80", - "recovery_mode": "condition_clear" - } - } + "role_id": 150 } } } } } }, - "/monit/rule/v2/update": { + "/role/permission/factor/list": { "post": { - "operationId": "monit-rule-write-update-v2", - "summary": "Update alert rule (V2)", - "description": "Replace an alert rule's V2 configuration in full by ID. Returns the updated rule.", + "operationId": "role-read-list-permission-factor", + "summary": "List permission factors", + "description": "List the permission factors granted to the calling member through their roles.", "tags": [ - "Monitors/Alert rules" + "Platform/Roles & permissions" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Alerting Rules Manage** (`monit`) |\n\n## Usage\n\n- `id` is required and the rule must already exist; otherwise the call returns `InvalidParameter`.\n- This is a full-field replacement: except for the cases below, fields you omit are stored as zero values (then normalized, e.g. `repeat_interval` becomes 3600). Fetch the full configuration via `/monit/rule/v2/info` before modifying it.\n- `enabled` must be passed explicitly (including `false`); omitting it returns `InvalidParameter`. Setting it to `false` clears the rule's active alerts.\n- `investigation_targets` is the exception: omit it to keep the current value, pass `[]` to clear, or pass a value to replace it entirely.\n- `folder_id` cannot be changed through this operation; use `/monit/rule/move` to move the rule to another folder.\n- The caller must be able to manage the rule's folder (account owner or admin, creator of the folder or one of its ancestors, or member of the team bound to the folder or an ancestor); otherwise the call returns `AccessDenied`.\n- `name` must be unique within the rule's folder; a duplicate returns `InvalidParameter`.\n- When `enabled` is `true`, `ds_type` must be a datasource type that supports alerting and every ID in `ds_ids` must be an enabled datasource with alerting turned on; otherwise the call returns `InvalidParameter`.\n- Callers other than the account owner or admins need read-only access to every datasource listed in `ds_ids` or currently matched by `ds_list`; otherwise the call returns `AccessDenied` (`no permission to reference datasource \"\"`).\n- The call fails with `AccessDenied` when the account already exceeds its alert rule license limit.\n- If the rule is modified by another request while this one is processed, the call returns HTTP 409 (`UndonedOrderExist`, `alert rule was modified; reload and retry`); fetch the rule again and retry.\n- `account_id`, `creator_*`, `updater_*`, `created_at`, and `updated_at` are maintained by the server; client-supplied values are ignored.\n- The request body may not exceed 1 MiB; a larger body returns HTTP 413 (`EntityTooLarge`). Additional unknown fields are ignored (forward compatibility).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/monitors/alert-rules/monit-rule-write-update-v2", + "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 a member credential: calls made with the account owner's credentials return `400 InvalidParameter`, because the account owner implicitly holds every permission.\n- Factors come from all roles the calling member holds and are deduplicated; the order is not stable. A member with no roles gets an empty array.\n- `factor_types` filters by type (`api`, `button`, `visit`, `menu`, `url`); omit it to return all types. An unsupported type returns `400`.", + "href": "/en/api-reference/platform/roles-permissions/role-read-list-permission-factor", "metadata": { - "sidebarTitle": "Update alert rule (V2)" + "sidebarTitle": "List permission factors" } }, "responses": { @@ -50703,7 +53341,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertRuleV2" + "$ref": "#/components/schemas/PermissionFactorListResponse" } } } @@ -50711,71 +53349,13 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "id": 50001, - "account_id": 888, - "folder_id": 100, - "name": "CPU High", - "labels": {}, - "ds_type": "prometheus", - "ds_list": [ - "prometheus*" - ], - "ds_ids": [], - "enabled": true, - "debug_log_enabled": false, - "rule_configs": { - "relate_queries": [], - "queries": [ - { - "name": "A", - "expr": "100 - avg(cpu_usage_idle)" - } - ], - "check_threshold": { - "enabled": true, - "alerting_check_times": 3, - "alerting_window_size": 5, - "recovery_check_times": 2, - "critical": "$A > 95", - "warning": "$A > 80", - "recovery_mode": "condition_clear" - } - }, - "cron_pattern": "0 * * * * *", - "timezone": "Asia/Shanghai", - "delay_seconds": 0, - "enabled_times": [ - { - "days": [ - 1, - 2, - 3, - 4, - 5, - 6, - 0 - ], - "stime": "00:00", - "etime": "23:59" - } - ], - "annotations": {}, - "description_type": "text", - "description": "", - "channel_ids": [ - 20001 - ], - "repeat_interval": 3600, - "repeat_total": 3, - "investigation_targets": [], - "creator_id": 66, - "creator_name": "zhangsan", - "updater_id": 66, - "updater_name": "zhangsan", - "created_at": 1712000000, - "updated_at": 1712003600 - } + "data": [ + { + "factor_name": "template:read:info", + "factor_type": "api", + "source": "system" + } + ] } } } @@ -50801,57 +53381,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertRuleV2" + "$ref": "#/components/schemas/PermissionFactorListRequest" }, "example": { - "folder_id": 100, - "name": "CPU High", - "ds_type": "prometheus", - "ds_list": [ - "prometheus*" - ], - "enabled": true, - "cron_pattern": "0 * * * * *", - "channel_ids": [ - 20001 - ], - "rule_configs": { - "queries": [ - { - "name": "A", - "expr": "100 - avg(cpu_usage_idle)" - } - ], - "check_threshold": { - "enabled": true, - "alerting_check_times": 3, - "alerting_window_size": 5, - "recovery_check_times": 2, - "critical": "$A > 95", - "warning": "$A > 80", - "recovery_mode": "condition_clear" - } - }, - "id": 50001 + "factor_types": [ + "api" + ] } } } } } }, - "/oncall/license/list": { + "/role/permission/list": { "post": { - "operationId": "oncall-license-read-license-list", - "summary": "List On-call licenses", - "description": "List people with active fixed or temporary On-call licenses in the current account.", + "operationId": "role-read-list-permission", + "summary": "List permissions", + "description": "List permission entries and mark which of them the given roles grant.", "tags": [ - "On-call/Licenses" + "Platform/Roles & permissions" ], "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- `items` contains only people with an active fixed or temporary On-call license.\n- For temporary licenses, `updated_by`, `created_at`, and `updated_at` are `0`.", - "href": "/en/api-reference/on-call/licenses/oncall-license-read-license-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- With `with_all: true`, every permission is returned and `is_granted` marks the ones granted by any role in `role_ids`.\n- With `with_all` false (the default), only the permissions granted by `role_ids` are returned — a call without `role_ids` returns an empty list.\n- `permission_name`, `description`, and `class` follow the request language (`Accept-Language` header, or the `locale`/`lang` query parameter).", + "href": "/en/api-reference/platform/roles-permissions/role-read-list-permission", "metadata": { - "sidebarTitle": "List On-call licenses" + "sidebarTitle": "List permissions" } }, "responses": { @@ -50868,35 +53422,28 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/LicenseListResponse" + "$ref": "#/components/schemas/RolePermissionListResponse" } } } ] }, "example": { - "request_id": "01J0D5Y31GY2TWAHRP3Q8K4M6N", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 2, "items": [ { - "person_id": 80011, - "person_name": "Yuki Zhang", - "type": "fixed", - "updated_by": 80001, - "created_at": 1719792000, - "updated_at": 1719878400 - }, - { - "person_id": 80012, - "person_name": "Alex Chen", - "type": "temporary", - "updated_by": 0, - "created_at": 0, - "updated_at": 0 + "id": 501, + "permission_name": "Templates Read", + "permission_type": "read", + "description": "View notification templates", + "class": "On-call", + "scope": "on-call", + "status": "enabled", + "is_granted": true, + "source": "system" } - ], - "release_limited": false + ] } } } @@ -50923,27 +53470,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/EmptyRequest" + "$ref": "#/components/schemas/RolePermissionListRequest" }, - "example": {} + "example": { + "role_ids": [ + 150 + ], + "with_all": true + } } } } } }, - "/person/infos": { + "/role/upsert": { "post": { - "operationId": "personInfos", - "summary": "Batch get persons", - "description": "Return profile information for a batch of person IDs (members or accounts).", + "operationId": "role-write-upsert", + "summary": "Create or update a role", + "description": "Create a new custom role or update an existing one. Pass `role_id` to update.", "tags": [ - "Platform/Members" + "Platform/Roles & permissions" ], "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- Including the account ID returns the account owner, with `as` `account`. Other IDs are looked up among the account's members, including removed ones (`status` `deleted`), so IDs saved in older records still resolve.\n- Duplicate IDs are deduplicated; IDs that match neither are omitted.", - "href": "/en/api-reference/platform/members/person-infos", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Omit `role_id` (or set it to 0) to create a role; a new ID is always assigned. Pass the ID of a custom role of your account to update it; any other ID returns `400 InvalidParameter` (`no role found by id`), and a built-in role ID (`2`, `6`, `8`) returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- `role_name` must be unique in the account, including the built-in names `Admin`, `Responder`, and `Viewer`; a conflict returns `400`.\n- An update overwrites `role_name`, `description`, and `permission_ids` together: omitting `description` clears it, and omitting `permission_ids` removes every permission from the role.\n- Updating a disabled role keeps it disabled; call `POST /role/enable` to enable it.\n- Every ID in `permission_ids` must be a permission returned by `POST /role/permission/list` (with `with_all: true`); otherwise the call returns `400` and nothing changes.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/platform/roles-permissions/role-write-upsert", "metadata": { - "sidebarTitle": "Batch get persons" + "sidebarTitle": "Create or update a role" } }, "responses": { @@ -50960,7 +53512,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PersonInfosResponse" + "$ref": "#/components/schemas/RoleUpsertResponse" } } } @@ -50969,31 +53521,8 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [ - { - "account_id": 2451002751131, - "person_id": 2476444212131, - "person_name": "Alice", - "avatar": "/image/avatar1.png", - "locale": "zh-CN", - "time_zone": "Asia/Shanghai", - "email": "alice@example.com", - "phone_verified": false, - "email_verified": true, - "as": "member", - "status": "enabled" - }, - { - "account_id": 2451002751131, - "person_id": 3790925372131, - "person_name": "Bob", - "email": "bob@example.com", - "phone_verified": false, - "email_verified": true, - "as": "member", - "status": "enabled" - } - ] + "role_id": 150, + "role_name": "On-call Manager" } } } @@ -51020,12 +53549,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PersonInfosRequest" + "$ref": "#/components/schemas/RoleUpsertRequest" }, "example": { - "person_ids": [ - 2476444212131, - 3790925372131 + "role_name": "On-call Manager", + "description": "Manage on-call rotations and incidents.", + "permission_ids": [ + 501, + 502 ] } } @@ -51033,19 +53564,19 @@ } } }, - "/role/delete": { + "/route/info": { "post": { - "operationId": "role-write-delete", - "summary": "Delete a role", - "description": "Delete a custom role, optionally revoking it from every member who still holds it.", + "operationId": "routeInfo", + "summary": "Get routing rule detail", + "description": "Return the routing rule of one shared integration.", "tags": [ - "Platform/Roles & permissions" + "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 | **Roles Manage** (`organization`) |\n\n## Usage\n\n- While members still hold the role, the call fails with `400 ReferenceExist` and lists them in `data.refs` (`kind` `member`); set `is_force` to `true` to revoke the role from all of them and then delete it.\n- A role selected as a default role in the SSO configuration cannot be deleted, even with `is_force`; the call fails with `400 ReferenceExist` until it is unselected there.\n- A role ID that does not exist or was already deleted is ignored and the call succeeds.\n- The built-in roles (`2`, `6`, `8`) cannot be deleted: with or without `is_force`, the call returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/roles-permissions/role-write-delete", + "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- When the integration has no routing rule, the response carries only `request_id`, with no `data` field.\n- A channel-exclusive or unknown `integration_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/route-info", "metadata": { - "sidebarTitle": "Delete a role" + "sidebarTitle": "Get routing rule detail" } }, "responses": { @@ -51062,7 +53593,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PlatformEmptyObject" + "$ref": "#/components/schemas/RouteItem" } } } @@ -51070,7 +53601,53 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "integration_id": 6113996590131, + "cases": [ + { + "if": [ + { + "key": "labels.check", + "oper": "IN", + "vals": [ + "cpu.idle<20%" + ] + } + ], + "channel_ids": [ + 2533748993131 + ], + "fallthrough": false, + "routing_mode": "standard" + }, + { + "if": [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Warning" + ] + } + ], + "channel_ids": null, + "fallthrough": false, + "routing_mode": "name_mapping", + "name_mapping_label": "labels.service" + } + ], + "default": { + "channel_ids": [ + 3521074710131 + ] + }, + "status": "enabled", + "version": 6, + "updated_by": 3790925372131, + "creator_id": 3790925372131, + "created_at": 1774606136, + "updated_at": 1774606136 + } } } } @@ -51096,29 +53673,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RoleDeleteRequest" + "$ref": "#/components/schemas/RouteInfoRequest" }, "example": { - "role_id": 150 + "integration_id": 6113996590131 } } } } } }, - "/role/disable": { + "/route/list": { "post": { - "operationId": "role-write-disable", - "summary": "Disable a role", - "description": "Set a custom role's status to disabled without deleting it.", + "operationId": "routeList", + "summary": "List routing rules", + "description": "Return the routing rules of several shared integrations in one call.", "tags": [ - "Platform/Roles & permissions" + "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 | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Only a role in `enabled` status can be disabled; calling it on a role that is already disabled returns `400 InvalidParameter`.\n- The built-in roles (`2`, `6`, `8`) cannot be disabled: the call returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- A role ID that does not exist or was deleted is ignored and the call succeeds.\n- Disabling does not revoke the role from the members who hold it, but a disabled role grants no permissions: those members, and the app keys they created, lose the role's permissions until it is enabled again.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/roles-permissions/role-write-disable", + "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- Integrations without a routing rule are omitted from `items`.\n- Every ID must be an existing shared integration; a single unknown or channel-exclusive ID fails the whole call with `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/route-list", "metadata": { - "sidebarTitle": "Disable a role" + "sidebarTitle": "List routing rules" } }, "responses": { @@ -51135,15 +53712,50 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PlatformEmptyObject" + "$ref": "#/components/schemas/ListRoutesResponse" } } - } - ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "integration_id": 6113996590131, + "cases": [ + { + "if": [ + { + "key": "labels.check", + "oper": "IN", + "vals": [ + "cpu.idle<20%" + ] + } + ], + "channel_ids": [ + 2533748993131 + ], + "fallthrough": false, + "routing_mode": "standard" + } + ], + "default": { + "channel_ids": [ + 3521074710131 + ] + }, + "status": "enabled", + "version": 6, + "updated_by": 3790925372131, + "creator_id": 3790925372131, + "created_at": 1774606136, + "updated_at": 1774606136 + } + ] + } } } } @@ -51169,29 +53781,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RoleIDRequest" + "$ref": "#/components/schemas/ListRoutesRequest" }, "example": { - "role_id": 150 + "integration_ids": [ + 6113996590131, + 6113996590132 + ] } } } } } }, - "/role/enable": { + "/route/upsert": { "post": { - "operationId": "role-write-enable", - "summary": "Enable a role", - "description": "Re-enable a previously disabled custom role.", + "operationId": "routeUpsert", + "summary": "Upsert routing rule", + "description": "Create or replace the routing rule that sends a shared integration's alerts to channels.", "tags": [ - "Platform/Roles & permissions" + "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 | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Only a role in `disabled` status can be enabled; calling it on an enabled role returns `400 InvalidParameter`.\n- The built-in roles (`2`, `6`, `8`) cannot be enabled or disabled: the call returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- Once enabled, the role's permissions apply again to the members who hold it and to the app keys those members created.\n- A role ID that does not exist or was deleted is ignored and the call succeeds.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/roles-permissions/role-write-enable", + "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- The whole rule is replaced: `cases`, `sections` or `default` missing from the request are removed. `version` increases on every call and the previous version is kept in the route history.\n- At least one of `cases` or `default` is required; a `default` with empty `channel_ids` counts as absent.\n- Only shared integrations have routing rules: a channel-exclusive or unknown `integration_id`, or a channel ID that does not exist, returns `InvalidParameter`.\n- When the integration belongs to a team, the caller must be the account owner or an admin, the integration's creator, or a member of that team; otherwise `AccessDenied`.\n- A successful response carries only `request_id`, with no `data` field.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/route-upsert", "metadata": { - "sidebarTitle": "Enable a role" + "sidebarTitle": "Upsert routing rule" } }, "responses": { @@ -51208,15 +53823,14 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PlatformEmptyObject" + "$ref": "#/components/schemas/EmptyResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } } @@ -51242,71 +53856,106 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/RoleIDRequest" + "$ref": "#/components/schemas/UpsertRouteRequest" }, "example": { - "role_id": 150 + "integration_id": 6113996590131, + "cases": [ + { + "if": [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Critical" + ] + } + ], + "channel_ids": [ + 3521074710131 + ], + "fallthrough": false, + "routing_mode": "standard" + } + ], + "default": { + "channel_ids": [ + 3521074710131 + ] + } } } } } } }, - "/role/info": { + "/rum/application/create": { "post": { - "operationId": "role-read-info", - "summary": "Get role detail", - "description": "Return the detail of a single role by its ID.", - "tags": [ - "Platform/Roles & permissions" - ], - "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 `2`, `6`, and `8` return the built-in Admin, Responder, and Viewer roles; their `description` follows the request language.\n- A role ID that does not exist or was deleted returns `400 InvalidParameter`.", - "href": "/en/api-reference/platform/roles-permissions/role-read-info", - "metadata": { - "sidebarTitle": "Get role detail" - } + "description": "Create a new RUM application. Returns the generated `application_id` and `client_token`.", + "operationId": "rum-application-write-create", + "requestBody": { + "content": { + "application/json": { + "example": { + "application_name": "My Web App", + "is_private": false, + "links": { + "enabled": true, + "systems": [ + { + "enabled": true, + "event_types": [ + "crash", + "error" + ], + "icon_color": "#0F766E", + "icon_text": "S3", + "id": "s3-crash-logs", + "name": "S3 Crash Logs", + "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" + } + ] + }, + "team_id": 2477033058131, + "type": "browser" + }, + "schema": { + "$ref": "#/components/schemas/RumApplicationCreateRequest" + } + } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "application_name": "My Web App", + "client_token": "e090078724855a4ca168c3884880dfbc131" + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RoleItem" + "$ref": "#/components/schemas/RumApplicationCreateResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "role_id": 2, - "role_name": "Admin", - "description": "Account Administrator, has all account permissions and can assist the main account in managing all affairs.", - "status": "enabled", - "permission_ids": [ - 101, - 102, - 201, - 701 - ], - "editable": false, - "created_at": 1653530940, - "updated_at": 1653530940 - } } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51324,119 +53973,62 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "Create application", + "tags": [ + "RUM/Applications" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- `type` must be one of: `browser`, `ios`, `android`, `react-native`, `flutter`, `kotlin-multiplatform`, `roku`, `unity`, `miniprogram`, `harmony`, `electron`.\n- `client_token` is generated by the server and used to initialize the RUM SDK; it is also returned later by `POST /rum/application/info`.\n- When `tracing` is sent, `open_type` (`popup` or `tab`) and an `http`/`https` `endpoint` are required even if `enabled` is `false`.\n- `links.systems[].url` must start with `http` or `https`; each system needs a `name` and at least one `event_types` entry.\n- With `alerting.delivery_mode` `oncall` (the default on Flashduty cloud), the server creates or reuses the account's RUM alerting integration and returns its ID as `alerting.integration_id`.\n- The team in `team_id` is not checked against the caller's own team memberships.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/rum/applications/rum-application-write-create", + "metadata": { + "sidebarTitle": "Create application" + } + } + } + }, + "/rum/application/delete": { + "post": { + "description": "Delete a RUM application by `application_id`.", + "operationId": "rum-application-write-delete", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/RoleInfoRequest" - }, "example": { - "role_id": 2 + "application_id": "qLpu24Dz4CAzWsESPbJYWA" + }, + "schema": { + "$ref": "#/components/schemas/RumApplicationIDRequest" } } - } - } - } - }, - "/role/list": { - "post": { - "operationId": "role-read-list", - "summary": "List roles", - "description": "Return all custom and built-in roles for the current account.", - "tags": [ - "Platform/Roles & permissions" - ], - "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- Custom roles (enabled and disabled) come first, sorted by `orderby`/`asc`; the three built-in roles — `2` Admin, `6` Responder, `8` Viewer — are appended at the end unless `no_global` is true, and are counted in `total`.\n- Built-in roles have `editable: false`, and their `description` follows the request language (`Accept-Language` header, or the `locale`/`lang` query parameter).", - "href": "/en/api-reference/platform/roles-permissions/role-read-list", - "metadata": { - "sidebarTitle": "List roles" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": {}, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RoleListResponse" + "$ref": "#/components/schemas/EmptyResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "total": 4, - "items": [ - { - "role_id": 150, - "role_name": "On-call Manager", - "description": "Manage on-call rotations and incidents.", - "status": "enabled", - "permission_ids": [ - 501, - 502 - ], - "editable": true, - "created_at": 1710000000, - "updated_at": 1712000000 - }, - { - "role_id": 2, - "role_name": "Admin", - "description": "Account Administrator, has all account permissions and can assist the main account in managing all affairs.", - "status": "enabled", - "permission_ids": [ - 101, - 102, - 201, - 701 - ], - "editable": false, - "created_at": 1653530940, - "updated_at": 1653530940 - }, - { - "role_id": 6, - "role_name": "Responder", - "description": "Responder, has standard permissions except billing center, member management, role management and single sign-on management, suitable for members handling daily operations.", - "status": "enabled", - "permission_ids": [ - 201, - 701 - ], - "editable": false, - "created_at": 1653530940, - "updated_at": 1653530940 - }, - { - "role_id": 8, - "role_name": "Viewer", - "description": "Viewer, has most read-only permissions except audit and onboarding, suitable for members who only need to view data.", - "status": "enabled", - "permission_ids": [ - 103 - ], - "editable": false, - "created_at": 1653530940, - "updated_at": 1653530940 - } - ] - } } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51454,63 +54046,113 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "Delete application", + "tags": [ + "RUM/Applications" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- Deletion is a soft delete: the application disappears from list, info and infos, and later calls with its ID fail (`InvalidParameter`, or `ResourceNotFound` for remote-config operations). There is no restore operation.\n- The application's `client_token` stops being accepted by the data intake within about 5 minutes; data already collected is not removed.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/rum/applications/rum-application-write-delete", + "metadata": { + "sidebarTitle": "Delete application" + } + } + } + }, + "/rum/application/info": { + "post": { + "description": "Retrieve full details of a single RUM application by `application_id`.", + "operationId": "rum-application-read-info", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/RoleListRequest" - }, "example": { - "orderby": "created_at", - "asc": false + "application_id": "WoyQQ3BohkdtPivubEvE8o" + }, + "schema": { + "$ref": "#/components/schemas/RumApplicationIDRequest" } } - } - } - } - }, - "/role/member/grant": { - "post": { - "operationId": "role-write-grant-role", - "summary": "Grant role to members", - "description": "Assign a role to one or more members, giving them its permissions.", - "tags": [ - "Platform/Roles & permissions" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Every ID in `member_ids` must be a member of the account, with no duplicates; otherwise the call returns `400` and nobody is changed.\n- `role_id` must be a built-in role or a custom role that has not been deleted (disabled roles are accepted, but grant no permissions until enabled); otherwise the call returns `400`.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Members who already hold the role keep it unchanged.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/roles-permissions/role-write-grant-role", - "metadata": { - "sidebarTitle": "Grant role to members" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "account_id": 2451002751131, + "alerting": { + "channel_ids": [ + 2490121812131 + ], + "enabled": true, + "integration_id": 4759595678131, + "delivery_mode": "oncall" + }, + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "application_name": "flashcat-rum", + "client_token": "a3cea433a8685a398cdfd68f54a45e06131", + "created_at": 1746673831462, + "created_by": 4441703362131, + "is_private": true, + "links": { + "enabled": true, + "systems": [ + { + "enabled": true, + "event_types": [ + "crash", + "error" + ], + "icon_color": "#0F766E", + "icon_text": "S3", + "id": "s3-crash-logs", + "name": "S3 Crash Logs", + "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" + } + ] + }, + "no_geo": false, + "no_ip": true, + "status": "enabled", + "team_id": 2477033058131, + "tracing": { + "enabled": false, + "endpoint": "", + "open_type": "" + }, + "type": "browser", + "updated_at": 1773398630657, + "updated_by": 3790925372131, + "repositories": [ + { + "repo": "acme/web-app", + "subdir": "apps/web" + } + ] + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PlatformEmptyObject" + "$ref": "#/components/schemas/RumApplicationItem" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51528,66 +54170,150 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "Get application detail", + "tags": [ + "RUM/Applications" + ], + "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 or deleted `application_id` returns `InvalidParameter`.\n- A private application (`is_private: true`) is readable only by the account owner, account admins, its creator and members of its owning team; others get `AccessDenied`.", + "href": "/en/api-reference/rum/applications/rum-application-read-info", + "metadata": { + "sidebarTitle": "Get application detail" + } + } + } + }, + "/rum/application/infos": { + "post": { + "description": "Retrieve details for multiple RUM applications by their IDs in one request.", + "operationId": "rum-application-read-infos", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/RoleGrantRequest" - }, "example": { - "member_ids": [ - 80011, - 80012 - ], - "role_id": 150 + "application_ids": [ + "eWbr4xk3ZRnLabRa6unqwD", + "WoyQQ3BohkdtPivubEvE8o" + ] + }, + "schema": { + "$ref": "#/components/schemas/RumApplicationInfosRequest" } } - } - } - } - }, - "/role/member/revoke": { - "post": { - "operationId": "role-write-revoke-role", - "summary": "Revoke role from members", - "description": "Remove a role from one or more members, revoking the permissions it granted.", - "tags": [ - "Platform/Roles & permissions" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Every ID in `member_ids` must be a member of the account, with no duplicates; otherwise the call returns `400` and nobody is changed.\n- `role_id` must be a built-in role or a custom role that has not been deleted (disabled roles are accepted); otherwise the call returns `400`.\n- Members provisioned through SSO cannot be changed while the SSO configuration marks them non-editable; the call returns `400`.\n- Members who don't hold the role are left unchanged; revoking a member's last role leaves them with no roles.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/roles-permissions/role-write-revoke-role", - "metadata": { - "sidebarTitle": "Revoke role from members" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "items": [ + { + "account_id": 2451002751131, + "alerting": { + "channel_ids": [ + 5962711836131, + 5967875767131 + ], + "enabled": true, + "integration_id": 4759595678131, + "delivery_mode": "oncall" + }, + "application_id": "eWbr4xk3ZRnLabRa6unqwD", + "application_name": "Flashduty DEV", + "client_token": "ce8d1be90fc6534f89ce36ebf526765e131", + "created_at": 1742958482000, + "created_by": 2476444212131, + "is_private": false, + "links": { + "enabled": false, + "systems": [] + }, + "no_geo": false, + "no_ip": false, + "status": "enabled", + "team_id": 2477033058131, + "tracing": { + "enabled": true, + "endpoint": "https://www.tracing.com/${trace_id}", + "open_type": "popup" + }, + "type": "browser", + "updated_at": 1772096392711, + "updated_by": 3122470302131, + "repositories": [] + }, + { + "account_id": 2451002751131, + "alerting": { + "channel_ids": [ + 2490121812131 + ], + "enabled": true, + "integration_id": 4759595678131, + "delivery_mode": "oncall" + }, + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "application_name": "flashcat-rum", + "client_token": "a3cea433a8685a398cdfd68f54a45e06131", + "created_at": 1746673831462, + "created_by": 4441703362131, + "is_private": true, + "links": { + "enabled": true, + "systems": [ + { + "enabled": true, + "event_types": [ + "crash", + "error" + ], + "icon_color": "#0F766E", + "icon_text": "S3", + "id": "s3-crash-logs", + "name": "S3 Crash Logs", + "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" + } + ] + }, + "no_geo": false, + "no_ip": true, + "status": "enabled", + "team_id": 2477033058131, + "tracing": { + "enabled": false, + "endpoint": "", + "open_type": "" + }, + "type": "browser", + "updated_at": 1773398630657, + "updated_by": 3790925372131, + "repositories": [] + } + ] + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PlatformEmptyObject" + "$ref": "#/components/schemas/RumApplicationInfosResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51605,71 +54331,152 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "Batch get applications", + "tags": [ + "RUM/Applications" + ], + "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- Duplicate IDs are collapsed; unknown or deleted IDs, and private applications the caller cannot access, are skipped without an error, so `items` can be shorter than `application_ids`.\n- The order of `items` is not guaranteed to follow `application_ids`.", + "href": "/en/api-reference/rum/applications/rum-application-read-infos", + "metadata": { + "sidebarTitle": "Batch get applications" + } + } + } + }, + "/rum/application/list": { + "post": { + "description": "Return a paginated list of RUM applications accessible to the current user.", + "operationId": "rum-application-read-list", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/RoleGrantRequest" - }, "example": { - "member_ids": [ - 80011 - ], - "role_id": 150 + "is_my_team": false, + "limit": 20, + "p": 1, + "query": "" + }, + "schema": { + "$ref": "#/components/schemas/RumApplicationListRequest" } } - } - } - } - }, - "/role/permission/factor/list": { - "post": { - "operationId": "role-read-list-permission-factor", - "summary": "List permission factors", - "description": "List the permission factors granted to the calling member through their roles.", - "tags": [ - "Platform/Roles & permissions" - ], - "x-mint": { - "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 a member credential: calls made with the account owner's credentials return `400 InvalidParameter`, because the account owner implicitly holds every permission.\n- Factors come from all roles the calling member holds and are deduplicated; the order is not stable. A member with no roles gets an empty array.\n- `factor_types` filters by type (`api`, `button`, `visit`, `menu`, `url`); omit it to return all types. An unsupported type returns `400`.", - "href": "/en/api-reference/platform/roles-permissions/role-read-list-permission-factor", - "metadata": { - "sidebarTitle": "List permission factors" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "has_next_page": true, + "items": [ + { + "account_id": 2451002751131, + "alerting": { + "channel_ids": [ + 2490121812131 + ], + "enabled": true, + "integration_id": 4759595678131, + "delivery_mode": "oncall" + }, + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "application_name": "flashcat-rum", + "client_token": "a3cea433a8685a398cdfd68f54a45e06131", + "created_at": 1746673831462, + "created_by": 4441703362131, + "is_private": true, + "links": { + "enabled": true, + "systems": [ + { + "enabled": true, + "event_types": [ + "crash", + "error" + ], + "icon_color": "#0F766E", + "icon_text": "S3", + "id": "s3-crash-logs", + "name": "S3 Crash Logs", + "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" + } + ] + }, + "no_geo": false, + "no_ip": true, + "status": "enabled", + "team_id": 2477033058131, + "tracing": { + "enabled": false, + "endpoint": "", + "open_type": "" + }, + "type": "browser", + "updated_at": 1773398630657, + "updated_by": 3790925372131, + "repositories": [] + }, + { + "account_id": 2451002751131, + "alerting": { + "channel_ids": [ + 5962711836131, + 5967875767131 + ], + "enabled": true, + "integration_id": 4759595678131, + "delivery_mode": "oncall" + }, + "application_id": "eWbr4xk3ZRnLabRa6unqwD", + "application_name": "Flashduty DEV", + "client_token": "ce8d1be90fc6534f89ce36ebf526765e131", + "created_at": 1742958482000, + "created_by": 2476444212131, + "is_private": false, + "links": { + "enabled": false, + "systems": [] + }, + "no_geo": false, + "no_ip": false, + "status": "enabled", + "team_id": 2477033058131, + "tracing": { + "enabled": true, + "endpoint": "https://www.tracing.com/${trace_id}", + "open_type": "popup" + }, + "type": "browser", + "updated_at": 1772096392711, + "updated_by": 3122470302131, + "repositories": [] + } + ], + "total": 7 + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/PermissionFactorListResponse" + "$ref": "#/components/schemas/RumApplicationListResponse" } - } - } - ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": [ - { - "factor_name": "template:read:info", - "factor_type": "api", - "source": "system" + }, + "type": "object" } ] } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51687,78 +54494,93 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "List applications", + "tags": [ + "RUM/Applications" + ], + "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- Private applications the caller cannot access are left out; the account owner and account admins see every application.\n- `is_my_team: true` keeps only applications owned by the caller's teams. If the caller's teams own no application, or the caller belongs to no team, the list is empty.\n- `team_id`, `query` and `is_my_team` combine with AND.\n- Sorted by `updated_at` descending unless `orderby`/`asc` say otherwise.", + "href": "/en/api-reference/rum/applications/rum-application-read-list", + "metadata": { + "sidebarTitle": "List applications" + } + } + } + }, + "/rum/application/remote-config/get": { + "post": { + "description": "Retrieve the live remote configuration of a RUM application and the version it is stored under.", + "operationId": "rum-application-remote-config-read-get", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/PermissionFactorListRequest" - }, "example": { - "factor_types": [ - "api" - ] + "application_id": "WoyQQ3BohkdtPivubEvE8o" + }, + "schema": { + "$ref": "#/components/schemas/GetRemoteConfigRequest" } } - } - } - } - }, - "/role/permission/list": { - "post": { - "operationId": "role-read-list-permission", - "summary": "List permissions", - "description": "List permission entries and mark which of them the given roles grant.", - "tags": [ - "Platform/Roles & permissions" - ], - "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- With `with_all: true`, every permission is returned and `is_granted` marks the ones granted by any role in `role_ids`.\n- With `with_all` false (the default), only the permissions granted by `role_ids` are returned — a call without `role_ids` returns an empty list.\n- `permission_name`, `description`, and `class` follow the request language (`Accept-Language` header, or the `locale`/`lang` query parameter).", - "href": "/en/api-reference/platform/roles-permissions/role-read-list-permission", - "metadata": { - "sidebarTitle": "List permissions" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "config": { + "activation": "next_session", + "custom": { + "feature_flags": { + "checkout_v2": true + } + }, + "default": { + "defaultPrivacyLevel": "mask-user-input", + "sessionReplaySampleRate": 20, + "sessionSampleRate": 100, + "traceSampleRate": 100 + }, + "enabled": true, + "refresh_on_foreground": false, + "rules": [ + { + "match": { + "env": "production" + }, + "set": { + "defaultPrivacyLevel": "mask", + "sessionReplaySampleRate": 0, + "sessionSampleRate": 5 + } + } + ] + }, + "updated_at": 1773398630657, + "version": 7 + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RolePermissionListResponse" + "$ref": "#/components/schemas/GetRemoteConfigResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "id": 501, - "permission_name": "Templates Read", - "permission_type": "read", - "description": "View notification templates", - "class": "On-call", - "scope": "on-call", - "status": "enabled", - "is_granted": true, - "source": "system" - } - ] - } } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51776,68 +54598,144 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "Get remote config detail", + "tags": [ + "RUM/Applications" + ], + "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- Before the first publish, `version` and `updated_at` are `0` and `config` is `null`; SDKs then run entirely on their init values.\n- A change reaches a client when its next session starts unless `activation` is `immediate`.\n- An unknown or deleted `application_id` returns `ResourceNotFound`. A private application (`is_private: true`) is readable only by the account owner, account admins, its creator and members of its owning team; others get `AccessDenied`.", + "href": "/en/api-reference/rum/applications/rum-application-remote-config-read-get", + "metadata": { + "sidebarTitle": "Get remote config detail" + } + } + } + }, + "/rum/application/remote-config/history/list": { + "post": { + "description": "List published remote configuration versions of a RUM application.", + "operationId": "rum-application-remote-config-read-history-list", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/RolePermissionListRequest" - }, "example": { - "role_ids": [ - 150 - ], - "with_all": true + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "asc": false, + "limit": 20, + "orderby": "updated_at", + "p": 0 + }, + "schema": { + "$ref": "#/components/schemas/ListRemoteConfigHistoryRequest" } } - } - } - } - }, - "/role/upsert": { - "post": { - "operationId": "role-write-upsert", - "summary": "Create or update a role", - "description": "Create a new custom role or update an existing one. Pass `role_id` to update.", - "tags": [ - "Platform/Roles & permissions" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Roles Manage** (`organization`) |\n\n## Usage\n\n- Omit `role_id` (or set it to 0) to create a role; a new ID is always assigned. Pass the ID of a custom role of your account to update it; any other ID returns `400 InvalidParameter` (`no role found by id`), and a built-in role ID (`2`, `6`, `8`) returns `400 InvalidParameter` (`Preset roles cannot be modified.`).\n- `role_name` must be unique in the account, including the built-in names `Admin`, `Responder`, and `Viewer`; a conflict returns `400`.\n- An update overwrites `role_name`, `description`, and `permission_ids` together: omitting `description` clears it, and omitting `permission_ids` removes every permission from the role.\n- Updating a disabled role keeps it disabled; call `POST /role/enable` to enable it.\n- Every ID in `permission_ids` must be a permission returned by `POST /role/permission/list` (with `with_all: true`); otherwise the call returns `400` and nothing changes.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/platform/roles-permissions/role-write-upsert", - "metadata": { - "sidebarTitle": "Create or update a role" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "has_next_page": false, + "items": [ + { + "config": { + "activation": "next_session", + "custom": { + "feature_flags": { + "checkout_v2": true + } + }, + "default": { + "defaultPrivacyLevel": "mask-user-input", + "sessionReplaySampleRate": 20, + "sessionSampleRate": 100, + "traceSampleRate": 100 + }, + "enabled": true, + "refresh_on_foreground": false, + "rules": [ + { + "match": { + "env": "production" + }, + "set": { + "defaultPrivacyLevel": "mask", + "sessionReplaySampleRate": 0, + "sessionSampleRate": 5 + } + } + ] + }, + "content_hash": "9f86d081884c7d65", + "reason": "Re-apply the v7 sampling after the test", + "updated_at": 1773398630657, + "updated_by": 4441703362131, + "updated_by_name": "Alice Zhang", + "version": 8, + "equivalent_to": 7 + }, + { + "config": { + "activation": "next_session", + "custom": { + "feature_flags": { + "checkout_v2": true + } + }, + "default": { + "defaultPrivacyLevel": "mask-user-input", + "sessionReplaySampleRate": 20, + "sessionSampleRate": 100, + "traceSampleRate": 100 + }, + "enabled": true, + "refresh_on_foreground": false, + "rules": [ + { + "match": { + "env": "production" + }, + "set": { + "defaultPrivacyLevel": "mask", + "sessionReplaySampleRate": 0, + "sessionSampleRate": 5 + } + } + ] + }, + "content_hash": "9f86d081884c7d65", + "reason": "", + "updated_at": 1772398630657, + "updated_by": 4441703362131, + "updated_by_name": "Alice Zhang", + "version": 7 + } + ], + "total": 3 + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RoleUpsertResponse" + "$ref": "#/components/schemas/ListRemoteConfigHistoryResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "role_id": 150, - "role_name": "On-call Manager" - } } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51855,113 +54753,66 @@ "$ref": "#/components/responses/ServerError" } }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RoleUpsertRequest" - }, - "example": { - "role_name": "On-call Manager", - "description": "Manage on-call rotations and incidents.", - "permission_ids": [ - 501, - 502 - ] - } - } - } - } - } - }, - "/route/info": { - "post": { - "operationId": "routeInfo", - "summary": "Get routing rule detail", - "description": "Return the routing rule of one shared integration.", + "summary": "List remote config history", "tags": [ - "On-call/Channels" + "RUM/Applications" ], "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- When the integration has no routing rule, the response carries only `request_id`, with no `data` field.\n- A channel-exclusive or unknown `integration_id` returns `InvalidParameter`.", - "href": "/en/api-reference/on-call/channels/route-info", + "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- Only the 50 most recent versions are kept; older versions are deleted when a new one is published and can no longer be listed or reverted to.\n- Newest first by default (`orderby=updated_at`, `asc=false`). An unrecognized `orderby` falls back to `updated_at`; ties are broken by `version`.\n- `content_hash` and `equivalent_to` identify versions with identical content, e.g. a revert that restored an earlier version.", + "href": "/en/api-reference/rum/applications/rum-application-remote-config-read-history-list", "metadata": { - "sidebarTitle": "Get routing rule detail" + "sidebarTitle": "List remote config history" } + } + } + }, + "/rum/application/remote-config/history/revert": { + "post": { + "description": "Republish an earlier remote configuration version's content as a new version.", + "operationId": "rum-application-remote-config-write-history-revert", + "requestBody": { + "content": { + "application/json": { + "example": { + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "reason": "Rolled back after the Q4 launch incident", + "version": 7 + }, + "schema": { + "$ref": "#/components/schemas/RevertRemoteConfigRequest" + } + } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "version": 9 + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RouteItem" + "$ref": "#/components/schemas/RevertRemoteConfigResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "integration_id": 6113996590131, - "cases": [ - { - "if": [ - { - "key": "labels.check", - "oper": "IN", - "vals": [ - "cpu.idle<20%" - ] - } - ], - "channel_ids": [ - 2533748993131 - ], - "fallthrough": false, - "routing_mode": "standard" - }, - { - "if": [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Warning" - ] - } - ], - "channel_ids": null, - "fallthrough": false, - "routing_mode": "name_mapping", - "name_mapping_label": "labels.service" - } - ], - "default": { - "channel_ids": [ - 3521074710131 - ] - }, - "status": "enabled", - "version": 6, - "updated_by": 3790925372131, - "creator_id": 3790925372131, - "created_at": 1774606136, - "updated_at": 1774606136 - } } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -51979,97 +54830,72 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "Revert remote config", + "tags": [ + "RUM/Applications" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- History is never rewritten: the revert publishes the earlier version's content under a new version number, which is returned.\n- `version` must still be in the retained history (the 50 most recent versions); otherwise the call returns `InvalidParameter` (`version not found`).\n- The restored content is validated against the current rules again and is rejected with `InvalidParameter` if it no longer passes.\n- The server does not generate a `reason`; an omitted `reason` is stored as an empty string.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/rum/applications/rum-application-remote-config-write-history-revert", + "metadata": { + "sidebarTitle": "Revert remote config" + } + } + } + }, + "/rum/application/remote-config/preview": { + "post": { + "description": "Evaluate a draft remote configuration against a client context without publishing it.", + "operationId": "rum-application-remote-config-read-preview", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteInfoRequest" - }, "example": { - "integration_id": 6113996590131 + "app_version": "2.14.3", + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "env": "production", + "sdk": "web@2.4.1" + }, + "schema": { + "$ref": "#/components/schemas/PreviewRemoteConfigRequest" } } - } - } - } - }, - "/route/list": { - "post": { - "operationId": "routeList", - "summary": "List routing rules", - "description": "Return the routing rules of several shared integrations in one call.", - "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 | **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Integrations without a routing rule are omitted from `items`.\n- Every ID must be an existing shared integration; a single unknown or channel-exclusive ID fails the whole call with `InvalidParameter`.", - "href": "/en/api-reference/on-call/channels/route-list", - "metadata": { - "sidebarTitle": "List routing rules" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "hit_rule_index": 0, + "values": { + "defaultPrivacyLevel": "mask", + "sessionReplaySampleRate": 0, + "sessionSampleRate": 5 + } + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListRoutesResponse" + "$ref": "#/components/schemas/PreviewRemoteConfigResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "integration_id": 6113996590131, - "cases": [ - { - "if": [ - { - "key": "labels.check", - "oper": "IN", - "vals": [ - "cpu.idle<20%" - ] - } - ], - "channel_ids": [ - 2533748993131 - ], - "fallthrough": false, - "routing_mode": "standard" - } - ], - "default": { - "channel_ids": [ - 3521074710131 - ] - }, - "status": "enabled", - "version": 6, - "updated_by": 3790925372131, - "creator_id": 3790925372131, - "created_at": 1774606136, - "updated_at": 1774606136 - } - ] - } } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -52087,64 +54913,93 @@ "$ref": "#/components/responses/ServerError" } }, + "summary": "Preview remote config", + "tags": [ + "RUM/Applications" + ], + "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- Runs the same rule matcher the SDK config endpoint uses and publishes nothing.\n- Omit `config` to preview the live configuration; a supplied `config` is validated like an update and invalid drafts return `InvalidParameter`.\n- Rule conditions compare exact strings; a rule that tests `env`, `app_version` or `sdk` never matches when that field is omitted from the request.\n- If the configuration is disabled (`enabled: false`) or has never been published, `values` is empty and `hit_rule_index` is `-1`.", + "href": "/en/api-reference/rum/applications/rum-application-remote-config-read-preview", + "metadata": { + "sidebarTitle": "Preview remote config" + } + } + } + }, + "/rum/application/remote-config/update": { + "post": { + "description": "Publish a complete new remote configuration version for a RUM application.", + "operationId": "rum-application-remote-config-write-update", "requestBody": { - "required": true, "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/ListRoutesRequest" - }, "example": { - "integration_ids": [ - 6113996590131, - 6113996590132 - ] + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "config": { + "activation": "next_session", + "custom": { + "feature_flags": { + "checkout_v2": true + } + }, + "default": { + "defaultPrivacyLevel": "mask-user-input", + "sessionReplaySampleRate": 20, + "sessionSampleRate": 100, + "traceSampleRate": 100 + }, + "enabled": true, + "refresh_on_foreground": false, + "rules": [ + { + "match": { + "env": "production" + }, + "set": { + "defaultPrivacyLevel": "mask", + "sessionReplaySampleRate": 0, + "sessionSampleRate": 5 + } + } + ] + }, + "reason": "Tighten replay sampling for the Q4 launch" + }, + "schema": { + "$ref": "#/components/schemas/UpdateRemoteConfigRequest" } } - } - } - } - }, - "/route/upsert": { - "post": { - "operationId": "routeUpsert", - "summary": "Upsert routing rule", - "description": "Create or replace the routing rule that sends a shared integration's alerts to channels.", - "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 | **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- The whole rule is replaced: `cases`, `sections` or `default` missing from the request are removed. `version` increases on every call and the previous version is kept in the route history.\n- At least one of `cases` or `default` is required; a `default` with empty `channel_ids` counts as absent.\n- Only shared integrations have routing rules: a channel-exclusive or unknown `integration_id`, or a channel ID that does not exist, returns `InvalidParameter`.\n- When the integration belongs to a team, the caller must be the account owner or an admin, the integration's creator, or a member of that team; otherwise `AccessDenied`.\n- A successful response carries only `request_id`, with no `data` field.\n- Every call is recorded in the account audit log.", - "href": "/en/api-reference/on-call/channels/route-upsert", - "metadata": { - "sidebarTitle": "Upsert routing rule" - } + }, + "required": true }, "responses": { "200": { - "description": "Success", "content": { "application/json": { + "example": { + "data": { + "version": 8 + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { - "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/UpdateRemoteConfigResponse" } - } + }, + "type": "object" } ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } - } + }, + "description": "Success" }, "400": { "$ref": "#/components/responses/BadRequest" @@ -52162,54 +55017,35 @@ "$ref": "#/components/responses/ServerError" } }, - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertRouteRequest" - }, - "example": { - "integration_id": 6113996590131, - "cases": [ - { - "if": [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Critical" - ] - } - ], - "channel_ids": [ - 3521074710131 - ], - "fallthrough": false, - "routing_mode": "standard" - } - ], - "default": { - "channel_ids": [ - 3521074710131 - ] - } - } - } + "summary": "Update remote config", + "tags": [ + "RUM/Applications" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- Send the complete configuration, not a patch: rule order is the priority, so a partial update has no unambiguous meaning.\n- Every call publishes a new version, even when the content is unchanged or `enabled` is `false`; only the 50 most recent versions are kept.\n- Call `POST /rum/application/remote-config/preview` first to check what clients would receive.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/rum/applications/rum-application-remote-config-write-update", + "metadata": { + "sidebarTitle": "Update remote config" } } } }, - "/rum/application/create": { + "/rum/application/update": { "post": { - "description": "Create a new RUM application. Returns the generated `application_id` and `client_token`.", - "operationId": "rum-application-write-create", + "description": "Update selected fields of a RUM application; fields left out of the request keep their current values.", + "operationId": "rum-application-write-update", "requestBody": { "content": { "application/json": { "example": { - "application_name": "My Web App", - "is_private": false, + "alerting": { + "channel_ids": [ + 2490121812131 + ], + "enabled": true + }, + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "application_name": "My Web App v2", "links": { "enabled": true, "systems": [ @@ -52226,12 +55062,10 @@ "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" } ] - }, - "team_id": 2477033058131, - "type": "browser" + } }, "schema": { - "$ref": "#/components/schemas/RumApplicationCreateRequest" + "$ref": "#/components/schemas/RumApplicationUpdateRequest" } } }, @@ -52242,11 +55076,7 @@ "content": { "application/json": { "example": { - "data": { - "application_id": "qLpu24Dz4CAzWsESPbJYWA", - "application_name": "My Web App", - "client_token": "e090078724855a4ca168c3884880dfbc131" - }, + "data": {}, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, "schema": { @@ -52257,7 +55087,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/RumApplicationCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } }, "type": "object" @@ -52284,31 +55114,32 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create application", + "summary": "Update application", "tags": [ "RUM/Applications" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- `type` must be one of: `browser`, `ios`, `android`, `react-native`, `flutter`, `kotlin-multiplatform`, `roku`, `unity`, `miniprogram`, `harmony`, `electron`.\n- `client_token` is generated by the server and used to initialize the RUM SDK; it is also returned later by `POST /rum/application/info`.\n- When `tracing` is sent, `open_type` (`popup` or `tab`) and an `http`/`https` `endpoint` are required even if `enabled` is `false`.\n- `links.systems[].url` must start with `http` or `https`; each system needs a `name` and at least one `event_types` entry.\n- With `alerting.delivery_mode` `oncall` (the default on Flashduty cloud), the server creates or reuses the account's RUM alerting integration and returns its ID as `alerting.integration_id`.\n- The team in `team_id` is not checked against the caller's own team memberships.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/rum/applications/rum-application-write-create", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- Only fields present in the request are changed. `alerting`, `tracing` and `links` replace the whole stored object when sent; `repositories` replaces the whole list.\n- When `tracing` is sent, `open_type` (`popup` or `tab`) and an `http`/`https` `endpoint` are required even if `enabled` is `false`.\n- `links.systems[].url` must start with `http` or `https`; each system needs a `name` and at least one `event_types` entry.\n- When `alerting` is sent with `delivery_mode` `oncall`, the existing `integration_id` is kept (or one is assigned); a client-supplied `integration_id` is ignored.\n- An unknown or deleted `application_id` returns `InvalidParameter`. The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/rum/applications/rum-application-write-update", "metadata": { - "sidebarTitle": "Create application" + "sidebarTitle": "Update application" } } } }, - "/rum/application/delete": { + "/rum/application/webhook/test": { "post": { - "description": "Delete a RUM application by `application_id`.", - "operationId": "rum-application-write-delete", + "description": "Send a sample RUM alert event to verify an application's webhook URL.", + "operationId": "rum-application-webhook-test", "requestBody": { "content": { "application/json": { "example": { - "application_id": "qLpu24Dz4CAzWsESPbJYWA" + "application_id": "WoyQQ3BohkdtPivubEvE8o", + "webhook_url": "https://hooks.example.com/rum-alerts" }, "schema": { - "$ref": "#/components/schemas/RumApplicationIDRequest" + "$ref": "#/components/schemas/RumWebhookTestRequest" } } }, @@ -52319,7 +55150,11 @@ "content": { "application/json": { "example": { - "data": {}, + "data": { + "message": "ok", + "ok": true, + "status_code": 200 + }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, "schema": { @@ -52330,58 +55165,249 @@ { "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RumWebhookTestResponse" + } + }, + "type": "object" + } + ] + } + } + }, + "description": "Success" + }, + "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" + } + }, + "summary": "Test application webhook", + "tags": [ + "RUM/Applications" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- The URL must use `http` or `https`; on Flashduty cloud, hosts that resolve to private, loopback, link-local or reserved addresses are rejected with `InvalidParameter`.\n- The sample body has the same shape as real alert events: `account_id`, `data_source_type` (`rum.alert`), `title`, `event_severity`, `event_status`, `description`, `alert_key`, `labels`, and `event_time` (Unix seconds).\n- Each attempt times out after 10 seconds; transport errors, 5xx and 429 responses are retried up to 2 times.\n- A failed delivery still returns HTTP 200 with `ok: false` and the reason in `message`.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.", + "href": "/en/api-reference/rum/applications/rum-application-webhook-test", + "metadata": { + "sidebarTitle": "Test application webhook" + } + } + } + }, + "/rum/dashboard/create": { + "post": { + "description": "Create a RUM custom dashboard from a full definition.", + "operationId": "rum-dashboard-write-create", + "requestBody": { + "content": { + "application/json": { + "example": { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "definition": { + "default_time_range": { + "from": "now-1h", + "to": "now" + }, + "description": "Loading time and error rate of the storefront.", + "refresh_interval": "1m", + "tabs": [ + { + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abd", + "sections": [ + { + "collapsed": false, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abe", + "panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 8, + "w": 16, + "x": 0, + "y": 4 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890ac0", + "queries": [ + { + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "draw_style": "bar", + "field": "view.loading_time", + "group_by": "view.url_path", + "limit": "20", + "scope": "view" + }, + "expr": "page:${page}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "Slowest pages by p95", + "viz_config": { + "column_options": { + "A": { + "display_name": "p95", + "threshold": { + "critical": 3000, + "mode": "higher_is_worse", + "warning": 1500 + }, + "threshold_display": "background", + "unit": "milliseconds" + }, + "view.url_path": { + "display_name": "Page", + "width_px": 320 + } + }, + "kind": "table", + "link_columns": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890ac1", + "pass_time": true, + "variable_mappings": { + "page": { + "column": "view.url_path", + "source": "row_column" + } + } + } + ], + "options": { + "dense": true + }, + "sort": [ + { + "direction": "desc", + "field": "A" + } + ] + } + } + ], + "title": "Slowest pages" + } + ], + "title": "Overview", + "top_panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 4, + "w": 8, + "x": 0, + "y": 0 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abf", + "queries": [ + { + "legend_alias": "p95 loading time", + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "field": "view.loading_time", + "scope": "view" + }, + "expr": "env:${env}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "p95 loading time", + "viz_config": { + "decimals": 0, + "kind": "stat", + "options": { + "sparkline": true + }, + "reducer": "max", + "unit": "milliseconds", + "value_fields": [ + "view.loading_time" + ] + } + } + ] + } + ], + "title": "Web performance overview", + "variables": [ + { + "default": { + "kind": "all" + }, + "kind": "custom", + "label": "Environment", + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" } + ], + "selection": { + "include_all": true, + "mode": "multi" + } + }, + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "default": { + "kind": "values", + "values": [ + "/checkout" + ] }, - "type": "object" + "kind": "query", + "label": "Page", + "name": "page", + "refresh": "on_dashboard_load", + "selection": { + "include_all": false, + "mode": "single" + }, + "variable_query": { + "field": "view.url_path", + "kind": "rum_field" + } } ] - } - } - }, - "description": "Success" - }, - "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" - } - }, - "summary": "Delete application", - "tags": [ - "RUM/Applications" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- Deletion is a soft delete: the application disappears from list, info and infos, and later calls with its ID fail (`InvalidParameter`, or `ResourceNotFound` for remote-config operations). There is no restore operation.\n- The application's `client_token` stops being accepted by the data intake within about 5 minutes; data already collected is not removed.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/rum/applications/rum-application-write-delete", - "metadata": { - "sidebarTitle": "Delete application" - } - } - } - }, - "/rum/application/info": { - "post": { - "description": "Retrieve full details of a single RUM application by `application_id`.", - "operationId": "rum-application-read-info", - "requestBody": { - "content": { - "application/json": { - "example": { - "application_id": "WoyQQ3BohkdtPivubEvE8o" + }, + "schema_version": "dashboard.v1" }, "schema": { - "$ref": "#/components/schemas/RumApplicationIDRequest" + "$ref": "#/components/schemas/RumDashboardCreateRequest" } } }, @@ -52393,56 +55419,209 @@ "application/json": { "example": { "data": { - "account_id": 2451002751131, - "alerting": { - "channel_ids": [ - 2490121812131 - ], - "enabled": true, - "integration_id": 4759595678131, - "delivery_mode": "oncall" + "created_at": 1792401120000, + "created_by": { + "id": 2477033058131, + "name": "Alex Chen" }, - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "application_name": "flashcat-rum", - "client_token": "a3cea433a8685a398cdfd68f54a45e06131", - "created_at": 1746673831462, - "created_by": 4441703362131, - "is_private": true, - "links": { - "enabled": true, - "systems": [ + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "definition": { + "default_time_range": { + "from": "now-1h", + "to": "now" + }, + "description": "Loading time and error rate of the storefront.", + "refresh_interval": "1m", + "tabs": [ { - "enabled": true, - "event_types": [ - "crash", - "error" + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abd", + "sections": [ + { + "collapsed": false, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abe", + "panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 8, + "w": 16, + "x": 0, + "y": 4 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890ac0", + "queries": [ + { + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "draw_style": "bar", + "field": "view.loading_time", + "group_by": "view.url_path", + "limit": "20", + "scope": "view" + }, + "expr": "page:${page}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "Slowest pages by p95", + "viz_config": { + "column_options": { + "A": { + "display_name": "p95", + "threshold": { + "critical": 3000, + "mode": "higher_is_worse", + "warning": 1500 + }, + "threshold_display": "background", + "unit": "milliseconds" + }, + "view.url_path": { + "display_name": "Page", + "width_px": 320 + } + }, + "kind": "table", + "link_columns": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890ac1", + "pass_time": true, + "variable_mappings": { + "page": { + "column": "view.url_path", + "source": "row_column" + } + } + } + ], + "options": { + "dense": true + }, + "sort": [ + { + "direction": "desc", + "field": "A" + } + ] + } + } + ], + "title": "Slowest pages" + } ], - "icon_color": "#0F766E", - "icon_text": "S3", - "id": "s3-crash-logs", - "name": "S3 Crash Logs", - "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" + "title": "Overview", + "top_panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 4, + "w": 8, + "x": 0, + "y": 0 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abf", + "queries": [ + { + "legend_alias": "p95 loading time", + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "field": "view.loading_time", + "scope": "view" + }, + "expr": "env:${env}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "p95 loading time", + "viz_config": { + "decimals": 0, + "kind": "stat", + "options": { + "sparkline": true + }, + "reducer": "max", + "unit": "milliseconds", + "value_fields": [ + "view.loading_time" + ] + } + } + ] + } + ], + "title": "Web performance overview", + "variables": [ + { + "default": { + "kind": "all" + }, + "kind": "custom", + "label": "Environment", + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + } + ], + "selection": { + "include_all": true, + "mode": "multi" + } + }, + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "default": { + "kind": "values", + "values": [ + "/checkout" + ] + }, + "kind": "query", + "label": "Page", + "name": "page", + "refresh": "on_dashboard_load", + "selection": { + "include_all": false, + "mode": "single" + }, + "variable_query": { + "field": "view.url_path", + "kind": "rum_field" + } } ] }, - "no_geo": false, - "no_ip": true, - "status": "enabled", - "team_id": 2477033058131, - "tracing": { - "enabled": false, - "endpoint": "", - "open_type": "" - }, - "type": "browser", - "updated_at": 1773398630657, - "updated_by": 3790925372131, - "repositories": [ - { - "repo": "acme/web-app", - "subdir": "apps/web" - } - ] + "revision": 1, + "schema_version": "dashboard.v1", + "updated_at": 1792401120000, + "updated_by": { + "id": 2477033058131, + "name": "Alex Chen" + } }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -52454,7 +55633,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/RumApplicationItem" + "$ref": "#/components/schemas/RumDashboardResource" } }, "type": "object" @@ -52474,6 +55653,36 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "A dashboard with this `dashboard_id` already exists. HTTP 409 `DashboardIDConflict`." + }, + "413": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The request body exceeds 2 MiB, the definition exceeds 1 MiB, or a count limit is exceeded. HTTP 413 `EntityTooLarge`." + }, + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "`schema_version` is not `dashboard.v1`. HTTP 422 `UnsupportedSchemaVersion`." + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -52481,34 +55690,32 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get application detail", + "summary": "Create dashboard", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "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 or deleted `application_id` returns `InvalidParameter`.\n- A private application (`is_private: true`) is readable only by the account owner, account admins, its creator and members of its owning team; others get `AccessDenied`.", - "href": "/en/api-reference/rum/applications/rum-application-read-info", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Dashboards Manage** (`rum`) |\n\n## Usage\n\n- `dashboard_id` is chosen by the caller and must be a canonical UUIDv7. Reusing an ID that already exists returns HTTP 409 `DashboardIDConflict`.\n- Every application a definition reads must exist in the account and be readable by the caller, otherwise the call fails with `InvalidParameter` or `AccessDenied`.\n- A failed `definition` validation returns HTTP 400 with up to 20 `violations`, each naming a `path`, a `rule` and a `message`, and the first one repeated as the error `message`.\n- Unknown request fields are rejected: the body is decoded strictly, so a typo fails with `InvalidParameter` instead of being ignored.\n- A body over 2 MiB, a definition over 1 MiB, or exceeding a count limit returns HTTP 413 `EntityTooLarge`; a `schema_version` other than `dashboard.v1` returns HTTP 422 `UnsupportedSchemaVersion`.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-write-create", "metadata": { - "sidebarTitle": "Get application detail" + "sidebarTitle": "Create dashboard" } } } }, - "/rum/application/infos": { + "/rum/dashboard/delete": { "post": { - "description": "Retrieve details for multiple RUM applications by their IDs in one request.", - "operationId": "rum-application-read-infos", + "description": "Move a dashboard to the trash under an expected-revision check.", + "operationId": "rum-dashboard-write-delete", "requestBody": { "content": { "application/json": { "example": { - "application_ids": [ - "eWbr4xk3ZRnLabRa6unqwD", - "WoyQQ3BohkdtPivubEvE8o" - ] + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "expected_revision": 3 }, "schema": { - "$ref": "#/components/schemas/RumApplicationInfosRequest" + "$ref": "#/components/schemas/RumDashboardMutationRequest" } } }, @@ -52520,90 +55727,8 @@ "application/json": { "example": { "data": { - "items": [ - { - "account_id": 2451002751131, - "alerting": { - "channel_ids": [ - 5962711836131, - 5967875767131 - ], - "enabled": true, - "integration_id": 4759595678131, - "delivery_mode": "oncall" - }, - "application_id": "eWbr4xk3ZRnLabRa6unqwD", - "application_name": "Flashduty DEV", - "client_token": "ce8d1be90fc6534f89ce36ebf526765e131", - "created_at": 1742958482000, - "created_by": 2476444212131, - "is_private": false, - "links": { - "enabled": false, - "systems": [] - }, - "no_geo": false, - "no_ip": false, - "status": "enabled", - "team_id": 2477033058131, - "tracing": { - "enabled": true, - "endpoint": "https://www.tracing.com/${trace_id}", - "open_type": "popup" - }, - "type": "browser", - "updated_at": 1772096392711, - "updated_by": 3122470302131, - "repositories": [] - }, - { - "account_id": 2451002751131, - "alerting": { - "channel_ids": [ - 2490121812131 - ], - "enabled": true, - "integration_id": 4759595678131, - "delivery_mode": "oncall" - }, - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "application_name": "flashcat-rum", - "client_token": "a3cea433a8685a398cdfd68f54a45e06131", - "created_at": 1746673831462, - "created_by": 4441703362131, - "is_private": true, - "links": { - "enabled": true, - "systems": [ - { - "enabled": true, - "event_types": [ - "crash", - "error" - ], - "icon_color": "#0F766E", - "icon_text": "S3", - "id": "s3-crash-logs", - "name": "S3 Crash Logs", - "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" - } - ] - }, - "no_geo": false, - "no_ip": true, - "status": "enabled", - "team_id": 2477033058131, - "tracing": { - "enabled": false, - "endpoint": "", - "open_type": "" - }, - "type": "browser", - "updated_at": 1773398630657, - "updated_by": 3790925372131, - "repositories": [] - } - ] + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "revision": 4 }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -52615,7 +55740,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/RumApplicationInfosResponse" + "$ref": "#/components/schemas/RumDashboardDeleteResponse" } }, "type": "object" @@ -52635,6 +55760,36 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard does not exist. HTTP 404 `DashboardNotFound`." + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard changed since `expected_revision` was read. HTTP 409 `DashboardRevisionConflict`." + }, + "410": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard is already in the trash. HTTP 410 `DashboardDeleted`." + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -52642,34 +55797,31 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Batch get applications", + "summary": "Delete dashboard", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "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- Duplicate IDs are collapsed; unknown or deleted IDs, and private applications the caller cannot access, are skipped without an error, so `items` can be shorter than `application_ids`.\n- The order of `items` is not guaranteed to follow `application_ids`.", - "href": "/en/api-reference/rum/applications/rum-application-read-infos", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Dashboards Manage** (`rum`) |\n\n## Usage\n\n- The dashboard is soft-deleted: it disappears from the list but stays in the trash for 30 days and can be restored with `POST /rum/dashboard/restore`.\n- Deleting an already deleted dashboard returns HTTP 410 `DashboardDeleted`; a stale `expected_revision` returns HTTP 409 `DashboardRevisionConflict`.\n- A dashboard that does not exist returns HTTP 404 `DashboardNotFound`.\n- The returned `revision` is the one created by the deletion. Pass it as `expected_revision` to restore the dashboard.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-write-delete", "metadata": { - "sidebarTitle": "Batch get applications" + "sidebarTitle": "Delete dashboard" } } } }, - "/rum/application/list": { + "/rum/dashboard/get": { "post": { - "description": "Return a paginated list of RUM applications accessible to the current user.", - "operationId": "rum-application-read-list", + "description": "Get one dashboard with its current definition and revision.", + "operationId": "rum-dashboard-read-get", "requestBody": { "content": { "application/json": { "example": { - "is_my_team": false, - "limit": 20, - "p": 1, - "query": "" + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc" }, "schema": { - "$ref": "#/components/schemas/RumApplicationListRequest" + "$ref": "#/components/schemas/RumDashboardIDRequest" } } }, @@ -52681,92 +55833,209 @@ "application/json": { "example": { "data": { - "has_next_page": true, - "items": [ - { - "account_id": 2451002751131, - "alerting": { - "channel_ids": [ - 2490121812131 + "created_at": 1792401120000, + "created_by": { + "id": 2477033058131, + "name": "Alex Chen" + }, + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "definition": { + "default_time_range": { + "from": "now-1h", + "to": "now" + }, + "description": "Loading time and error rate of the storefront.", + "refresh_interval": "1m", + "tabs": [ + { + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abd", + "sections": [ + { + "collapsed": false, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abe", + "panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 8, + "w": 16, + "x": 0, + "y": 4 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890ac0", + "queries": [ + { + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "draw_style": "bar", + "field": "view.loading_time", + "group_by": "view.url_path", + "limit": "20", + "scope": "view" + }, + "expr": "page:${page}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "Slowest pages by p95", + "viz_config": { + "column_options": { + "A": { + "display_name": "p95", + "threshold": { + "critical": 3000, + "mode": "higher_is_worse", + "warning": 1500 + }, + "threshold_display": "background", + "unit": "milliseconds" + }, + "view.url_path": { + "display_name": "Page", + "width_px": 320 + } + }, + "kind": "table", + "link_columns": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890ac1", + "pass_time": true, + "variable_mappings": { + "page": { + "column": "view.url_path", + "source": "row_column" + } + } + } + ], + "options": { + "dense": true + }, + "sort": [ + { + "direction": "desc", + "field": "A" + } + ] + } + } + ], + "title": "Slowest pages" + } ], - "enabled": true, - "integration_id": 4759595678131, - "delivery_mode": "oncall" - }, - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "application_name": "flashcat-rum", - "client_token": "a3cea433a8685a398cdfd68f54a45e06131", - "created_at": 1746673831462, - "created_by": 4441703362131, - "is_private": true, - "links": { - "enabled": true, - "systems": [ + "title": "Overview", + "top_panels": [ { - "enabled": true, - "event_types": [ - "crash", - "error" + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 4, + "w": 8, + "x": 0, + "y": 0 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abf", + "queries": [ + { + "legend_alias": "p95 loading time", + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "field": "view.loading_time", + "scope": "view" + }, + "expr": "env:${env}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } ], - "icon_color": "#0F766E", - "icon_text": "S3", - "id": "s3-crash-logs", - "name": "S3 Crash Logs", - "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" + "title": "p95 loading time", + "viz_config": { + "decimals": 0, + "kind": "stat", + "options": { + "sparkline": true + }, + "reducer": "max", + "unit": "milliseconds", + "value_fields": [ + "view.loading_time" + ] + } } ] - }, - "no_geo": false, - "no_ip": true, - "status": "enabled", - "team_id": 2477033058131, - "tracing": { - "enabled": false, - "endpoint": "", - "open_type": "" - }, - "type": "browser", - "updated_at": 1773398630657, - "updated_by": 3790925372131, - "repositories": [] - }, - { - "account_id": 2451002751131, - "alerting": { - "channel_ids": [ - 5962711836131, - 5967875767131 + } + ], + "title": "Web performance overview", + "variables": [ + { + "default": { + "kind": "all" + }, + "kind": "custom", + "label": "Environment", + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + } ], - "enabled": true, - "integration_id": 4759595678131, - "delivery_mode": "oncall" - }, - "application_id": "eWbr4xk3ZRnLabRa6unqwD", - "application_name": "Flashduty DEV", - "client_token": "ce8d1be90fc6534f89ce36ebf526765e131", - "created_at": 1742958482000, - "created_by": 2476444212131, - "is_private": false, - "links": { - "enabled": false, - "systems": [] - }, - "no_geo": false, - "no_ip": false, - "status": "enabled", - "team_id": 2477033058131, - "tracing": { - "enabled": true, - "endpoint": "https://www.tracing.com/${trace_id}", - "open_type": "popup" - }, - "type": "browser", - "updated_at": 1772096392711, - "updated_by": 3122470302131, - "repositories": [] - } - ], - "total": 7 + "selection": { + "include_all": true, + "mode": "multi" + } + }, + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "default": { + "kind": "values", + "values": [ + "/checkout" + ] + }, + "kind": "query", + "label": "Page", + "name": "page", + "refresh": "on_dashboard_load", + "selection": { + "include_all": false, + "mode": "single" + }, + "variable_query": { + "field": "view.url_path", + "kind": "rum_field" + } + } + ] + }, + "revision": 3, + "schema_version": "dashboard.v1", + "updated_at": 1792404240000, + "updated_by": { + "id": 2477033058177, + "name": "Mei Lin" + } }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -52778,7 +56047,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/RumApplicationListResponse" + "$ref": "#/components/schemas/RumDashboardResource" } }, "type": "object" @@ -52798,6 +56067,26 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard does not exist. HTTP 404 `DashboardNotFound`." + }, + "410": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard is in the trash. HTTP 410 `DashboardDeleted`." + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -52805,31 +56094,39 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List applications", + "summary": "Get dashboard detail", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "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- Private applications the caller cannot access are left out; the account owner and account admins see every application.\n- `is_my_team: true` keeps only applications owned by the caller's teams. If the caller's teams own no application, or the caller belongs to no team, the list is empty.\n- `team_id`, `query` and `is_my_team` combine with AND.\n- Sorted by `updated_at` descending unless `orderby`/`asc` say otherwise.", - "href": "/en/api-reference/rum/applications/rum-application-read-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | Any valid `app_key` |\n\n## Usage\n\n- A dashboard in the trash returns HTTP 410 `DashboardDeleted`; restore it first. A missing one returns HTTP 404 `DashboardNotFound`.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-read-get", "metadata": { - "sidebarTitle": "List applications" + "sidebarTitle": "Get dashboard detail" } } } }, - "/rum/application/remote-config/get": { + "/rum/dashboard/list": { "post": { - "description": "Retrieve the live remote configuration of a RUM application and the version it is stored under.", - "operationId": "rum-application-remote-config-read-get", + "description": "List the account's dashboards, newest change first by default.", + "operationId": "rum-dashboard-read-list", "requestBody": { "content": { "application/json": { "example": { - "application_id": "WoyQQ3BohkdtPivubEvE8o" + "limit": 20, + "p": 1, + "query": "performance", + "sort": [ + { + "direction": "desc", + "field": "updated_at" + } + ] }, "schema": { - "$ref": "#/components/schemas/GetRemoteConfigRequest" + "$ref": "#/components/schemas/RumDashboardListRequest" } } }, @@ -52841,36 +56138,20 @@ "application/json": { "example": { "data": { - "config": { - "activation": "next_session", - "custom": { - "feature_flags": { - "checkout_v2": true - } - }, - "default": { - "defaultPrivacyLevel": "mask-user-input", - "sessionReplaySampleRate": 20, - "sessionSampleRate": 100, - "traceSampleRate": 100 - }, - "enabled": true, - "refresh_on_foreground": false, - "rules": [ - { - "match": { - "env": "production" - }, - "set": { - "defaultPrivacyLevel": "mask", - "sessionReplaySampleRate": 0, - "sessionSampleRate": 5 - } + "items": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "description": "Loading time and error rate of the storefront.", + "revision": 3, + "title": "Web performance overview", + "updated_at": 1792404240000, + "updated_by": { + "id": 2477033058177, + "name": "Mei Lin" } - ] - }, - "updated_at": 1773398630657, - "version": 7 + } + ], + "total": 7 }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -52882,7 +56163,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/GetRemoteConfigResponse" + "$ref": "#/components/schemas/RumDashboardListResponse" } }, "type": "object" @@ -52909,35 +56190,32 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get remote config detail", + "summary": "List dashboards", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "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- Before the first publish, `version` and `updated_at` are `0` and `config` is `null`; SDKs then run entirely on their init values.\n- A change reaches a client when its next session starts unless `activation` is `immediate`.\n- An unknown or deleted `application_id` returns `ResourceNotFound`. A private application (`is_private: true`) is readable only by the account owner, account admins, its creator and members of its owning team; others get `AccessDenied`.", - "href": "/en/api-reference/rum/applications/rum-application-remote-config-read-get", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | Any valid `app_key` |\n\n## Usage\n\n- The definition is not returned; call `POST /rum/dashboard/get` for one dashboard.\n- `query` matches the title or description; every space-separated word must match. Deleted dashboards are listed by `POST /rum/dashboard/trash/list` instead.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-read-list", "metadata": { - "sidebarTitle": "Get remote config detail" + "sidebarTitle": "List dashboards" } } } }, - "/rum/application/remote-config/history/list": { + "/rum/dashboard/restore": { "post": { - "description": "List published remote configuration versions of a RUM application.", - "operationId": "rum-application-remote-config-read-history-list", + "description": "Restore a dashboard from the trash as a new revision.", + "operationId": "rum-dashboard-write-restore", "requestBody": { "content": { "application/json": { "example": { - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "asc": false, - "limit": 20, - "orderby": "updated_at", - "p": 0 + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "expected_revision": 4 }, "schema": { - "$ref": "#/components/schemas/ListRemoteConfigHistoryRequest" + "$ref": "#/components/schemas/RumDashboardMutationRequest" } } }, @@ -52949,83 +56227,209 @@ "application/json": { "example": { "data": { - "has_next_page": false, - "items": [ - { - "config": { - "activation": "next_session", - "custom": { - "feature_flags": { - "checkout_v2": true + "created_at": 1792401120000, + "created_by": { + "id": 2477033058131, + "name": "Alex Chen" + }, + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "definition": { + "default_time_range": { + "from": "now-1h", + "to": "now" + }, + "description": "Loading time and error rate of the storefront.", + "refresh_interval": "1m", + "tabs": [ + { + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abd", + "sections": [ + { + "collapsed": false, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abe", + "panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 8, + "w": 16, + "x": 0, + "y": 4 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890ac0", + "queries": [ + { + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "draw_style": "bar", + "field": "view.loading_time", + "group_by": "view.url_path", + "limit": "20", + "scope": "view" + }, + "expr": "page:${page}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "Slowest pages by p95", + "viz_config": { + "column_options": { + "A": { + "display_name": "p95", + "threshold": { + "critical": 3000, + "mode": "higher_is_worse", + "warning": 1500 + }, + "threshold_display": "background", + "unit": "milliseconds" + }, + "view.url_path": { + "display_name": "Page", + "width_px": 320 + } + }, + "kind": "table", + "link_columns": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890ac1", + "pass_time": true, + "variable_mappings": { + "page": { + "column": "view.url_path", + "source": "row_column" + } + } + } + ], + "options": { + "dense": true + }, + "sort": [ + { + "direction": "desc", + "field": "A" + } + ] + } + } + ], + "title": "Slowest pages" } - }, - "default": { - "defaultPrivacyLevel": "mask-user-input", - "sessionReplaySampleRate": 20, - "sessionSampleRate": 100, - "traceSampleRate": 100 - }, - "enabled": true, - "refresh_on_foreground": false, - "rules": [ + ], + "title": "Overview", + "top_panels": [ { - "match": { - "env": "production" + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" }, - "set": { - "defaultPrivacyLevel": "mask", - "sessionReplaySampleRate": 0, - "sessionSampleRate": 5 + "grid": { + "h": 4, + "w": 8, + "x": 0, + "y": 0 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abf", + "queries": [ + { + "legend_alias": "p95 loading time", + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "field": "view.loading_time", + "scope": "view" + }, + "expr": "env:${env}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "p95 loading time", + "viz_config": { + "decimals": 0, + "kind": "stat", + "options": { + "sparkline": true + }, + "reducer": "max", + "unit": "milliseconds", + "value_fields": [ + "view.loading_time" + ] } } ] - }, - "content_hash": "9f86d081884c7d65", - "reason": "Re-apply the v7 sampling after the test", - "updated_at": 1773398630657, - "updated_by": 4441703362131, - "updated_by_name": "Alice Zhang", - "version": 8, - "equivalent_to": 7 - }, - { - "config": { - "activation": "next_session", - "custom": { - "feature_flags": { - "checkout_v2": true - } - }, + } + ], + "title": "Web performance overview", + "variables": [ + { "default": { - "defaultPrivacyLevel": "mask-user-input", - "sessionReplaySampleRate": 20, - "sessionSampleRate": 100, - "traceSampleRate": 100 + "kind": "all" }, - "enabled": true, - "refresh_on_foreground": false, - "rules": [ + "kind": "custom", + "label": "Environment", + "name": "env", + "options": [ { - "match": { - "env": "production" - }, - "set": { - "defaultPrivacyLevel": "mask", - "sessionReplaySampleRate": 0, - "sessionSampleRate": 5 - } + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" } - ] + ], + "selection": { + "include_all": true, + "mode": "multi" + } }, - "content_hash": "9f86d081884c7d65", - "reason": "", - "updated_at": 1772398630657, - "updated_by": 4441703362131, - "updated_by_name": "Alice Zhang", - "version": 7 - } - ], - "total": 3 + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "default": { + "kind": "values", + "values": [ + "/checkout" + ] + }, + "kind": "query", + "label": "Page", + "name": "page", + "refresh": "on_dashboard_load", + "selection": { + "include_all": false, + "mode": "single" + }, + "variable_query": { + "field": "view.url_path", + "kind": "rum_field" + } + } + ] + }, + "revision": 5, + "schema_version": "dashboard.v1", + "updated_at": 1792404240000, + "updated_by": { + "id": 2477033058177, + "name": "Mei Lin" + } }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -53037,7 +56441,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/ListRemoteConfigHistoryResponse" + "$ref": "#/components/schemas/RumDashboardResource" } }, "type": "object" @@ -53057,6 +56461,26 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard is not in the trash, or was purged after the 30-day retention window. HTTP 404 `DashboardNotFound`." + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard changed since `expected_revision` was read. HTTP 409 `DashboardRevisionConflict`." + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -53064,33 +56488,32 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List remote config history", + "summary": "Restore dashboard", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "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- Only the 50 most recent versions are kept; older versions are deleted when a new one is published and can no longer be listed or reverted to.\n- Newest first by default (`orderby=updated_at`, `asc=false`). An unrecognized `orderby` falls back to `updated_at`; ties are broken by `version`.\n- `content_hash` and `equivalent_to` identify versions with identical content, e.g. a revert that restored an earlier version.", - "href": "/en/api-reference/rum/applications/rum-application-remote-config-read-history-list", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Dashboards Manage** (`rum`) |\n\n## Usage\n\n- Only a dashboard in the trash can be restored. A live dashboard, or one purged after the 30-day retention window, returns HTTP 404 `DashboardNotFound`. Pass the `revision` that delete returned (or the trash list shows) as `expected_revision`.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-write-restore", "metadata": { - "sidebarTitle": "List remote config history" + "sidebarTitle": "Restore dashboard" } } } }, - "/rum/application/remote-config/history/revert": { + "/rum/dashboard/revisions/get": { "post": { - "description": "Republish an earlier remote configuration version's content as a new version.", - "operationId": "rum-application-remote-config-write-history-revert", + "description": "Get one revision of a dashboard with its full definition.", + "operationId": "rum-dashboard-read-revision-get", "requestBody": { "content": { "application/json": { "example": { - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "reason": "Rolled back after the Q4 launch incident", - "version": 7 + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "revision": 3 }, "schema": { - "$ref": "#/components/schemas/RevertRemoteConfigRequest" + "$ref": "#/components/schemas/RumDashboardRevisionGetRequest" } } }, @@ -53102,7 +56525,205 @@ "application/json": { "example": { "data": { - "version": 9 + "actor": { + "id": 2477033058177, + "name": "Mei Lin" + }, + "created_at": 1792404240000, + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "definition": { + "default_time_range": { + "from": "now-1h", + "to": "now" + }, + "description": "Loading time and error rate of the storefront.", + "refresh_interval": "1m", + "tabs": [ + { + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abd", + "sections": [ + { + "collapsed": false, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abe", + "panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 8, + "w": 16, + "x": 0, + "y": 4 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890ac0", + "queries": [ + { + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "draw_style": "bar", + "field": "view.loading_time", + "group_by": "view.url_path", + "limit": "20", + "scope": "view" + }, + "expr": "page:${page}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "Slowest pages by p95", + "viz_config": { + "column_options": { + "A": { + "display_name": "p95", + "threshold": { + "critical": 3000, + "mode": "higher_is_worse", + "warning": 1500 + }, + "threshold_display": "background", + "unit": "milliseconds" + }, + "view.url_path": { + "display_name": "Page", + "width_px": 320 + } + }, + "kind": "table", + "link_columns": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890ac1", + "pass_time": true, + "variable_mappings": { + "page": { + "column": "view.url_path", + "source": "row_column" + } + } + } + ], + "options": { + "dense": true + }, + "sort": [ + { + "direction": "desc", + "field": "A" + } + ] + } + } + ], + "title": "Slowest pages" + } + ], + "title": "Overview", + "top_panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 4, + "w": 8, + "x": 0, + "y": 0 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abf", + "queries": [ + { + "legend_alias": "p95 loading time", + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "field": "view.loading_time", + "scope": "view" + }, + "expr": "env:${env}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "p95 loading time", + "viz_config": { + "decimals": 0, + "kind": "stat", + "options": { + "sparkline": true + }, + "reducer": "max", + "unit": "milliseconds", + "value_fields": [ + "view.loading_time" + ] + } + } + ] + } + ], + "title": "Web performance overview", + "variables": [ + { + "default": { + "kind": "all" + }, + "kind": "custom", + "label": "Environment", + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + } + ], + "selection": { + "include_all": true, + "mode": "multi" + } + }, + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "default": { + "kind": "values", + "values": [ + "/checkout" + ] + }, + "kind": "query", + "label": "Page", + "name": "page", + "refresh": "on_dashboard_load", + "selection": { + "include_all": false, + "mode": "single" + }, + "variable_query": { + "field": "view.url_path", + "kind": "rum_field" + } + } + ] + }, + "message": "Raise the p95 threshold", + "revision": 3, + "schema_version": "dashboard.v1" }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -53114,7 +56735,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/RevertRemoteConfigResponse" + "$ref": "#/components/schemas/RumDashboardRevisionResource" } }, "type": "object" @@ -53134,6 +56755,26 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard or the revision does not exist; old revisions are pruned. HTTP 404 `DashboardNotFound`." + }, + "410": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard is in the trash. HTTP 410 `DashboardDeleted`." + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -53141,34 +56782,31 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Revert remote config", + "summary": "Get dashboard revision", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- History is never rewritten: the revert publishes the earlier version's content under a new version number, which is returned.\n- `version` must still be in the retained history (the 50 most recent versions); otherwise the call returns `InvalidParameter` (`version not found`).\n- The restored content is validated against the current rules again and is rejected with `InvalidParameter` if it no longer passes.\n- The server does not generate a `reason`; an omitted `reason` is stored as an empty string.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/rum/applications/rum-application-remote-config-write-history-revert", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | Any valid `app_key` |\n\n## Usage\n\n- Reading a revision that has been pruned from the history returns HTTP 404.\n- A dashboard in the trash returns HTTP 410 `DashboardDeleted`.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-read-revision-get", "metadata": { - "sidebarTitle": "Revert remote config" + "sidebarTitle": "Get dashboard revision" } } } }, - "/rum/application/remote-config/preview": { + "/rum/dashboard/revisions/list": { "post": { - "description": "Evaluate a draft remote configuration against a client context without publishing it.", - "operationId": "rum-application-remote-config-read-preview", + "description": "List a dashboard's revision history, newest first.", + "operationId": "rum-dashboard-read-revision-list", "requestBody": { "content": { "application/json": { "example": { - "app_version": "2.14.3", - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "env": "production", - "sdk": "web@2.4.1" + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc" }, "schema": { - "$ref": "#/components/schemas/PreviewRemoteConfigRequest" + "$ref": "#/components/schemas/RumDashboardIDRequest" } } }, @@ -53180,12 +56818,18 @@ "application/json": { "example": { "data": { - "hit_rule_index": 0, - "values": { - "defaultPrivacyLevel": "mask", - "sessionReplaySampleRate": 0, - "sessionSampleRate": 5 - } + "items": [ + { + "actor": { + "id": 2477033058177, + "name": "Mei Lin" + }, + "created_at": 1792404240000, + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "message": "Raise the p95 threshold", + "revision": 3 + } + ] }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -53197,7 +56841,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/PreviewRemoteConfigResponse" + "$ref": "#/components/schemas/RumDashboardRevisionListResponse" } }, "type": "object" @@ -53217,6 +56861,26 @@ "403": { "$ref": "#/components/responses/Forbidden" }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard does not exist. HTTP 404 `DashboardNotFound`." + }, + "410": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard is in the trash. HTTP 410 `DashboardDeleted`." + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -53224,60 +56888,38 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Preview remote config", + "summary": "List dashboard revisions", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "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- Runs the same rule matcher the SDK config endpoint uses and publishes nothing.\n- Omit `config` to preview the live configuration; a supplied `config` is validated like an update and invalid drafts return `InvalidParameter`.\n- Rule conditions compare exact strings; a rule that tests `env`, `app_version` or `sdk` never matches when that field is omitted from the request.\n- If the configuration is disabled (`enabled: false`) or has never been published, `values` is empty and `hit_rule_index` is `-1`.", - "href": "/en/api-reference/rum/applications/rum-application-remote-config-read-preview", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | Any valid `app_key` |\n\n## Usage\n\n- Up to 20 revisions are kept; older ones are pruned. Definitions are not returned here — use `POST /rum/dashboard/revisions/get` for one.\n- A dashboard that does not exist returns HTTP 404 `DashboardNotFound`; one in the trash returns HTTP 410 `DashboardDeleted`.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-read-revision-list", "metadata": { - "sidebarTitle": "Preview remote config" + "sidebarTitle": "List dashboard revisions" } } } }, - "/rum/application/remote-config/update": { + "/rum/dashboard/trash/list": { "post": { - "description": "Publish a complete new remote configuration version for a RUM application.", - "operationId": "rum-application-remote-config-write-update", + "description": "List the deleted dashboards, newest deletion first by default.", + "operationId": "rum-dashboard-read-trash-list", "requestBody": { "content": { "application/json": { "example": { - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "config": { - "activation": "next_session", - "custom": { - "feature_flags": { - "checkout_v2": true - } - }, - "default": { - "defaultPrivacyLevel": "mask-user-input", - "sessionReplaySampleRate": 20, - "sessionSampleRate": 100, - "traceSampleRate": 100 - }, - "enabled": true, - "refresh_on_foreground": false, - "rules": [ - { - "match": { - "env": "production" - }, - "set": { - "defaultPrivacyLevel": "mask", - "sessionReplaySampleRate": 0, - "sessionSampleRate": 5 - } - } - ] - }, - "reason": "Tighten replay sampling for the Q4 launch" + "limit": 20, + "p": 1, + "sort": [ + { + "direction": "desc", + "field": "deleted_at" + } + ] }, "schema": { - "$ref": "#/components/schemas/UpdateRemoteConfigRequest" + "$ref": "#/components/schemas/RumDashboardTrashListRequest" } } }, @@ -53289,7 +56931,20 @@ "application/json": { "example": { "data": { - "version": 8 + "items": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "deleted_at": 1792404240000, + "deleted_by": { + "id": 2477033058177, + "name": "Mei Lin" + }, + "description": "Loading time and error rate of the storefront.", + "revision": 4, + "title": "Web performance overview" + } + ], + "total": 2 }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, @@ -53301,7 +56956,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/UpdateRemoteConfigResponse" + "$ref": "#/components/schemas/RumDashboardTrashListResponse" } }, "type": "object" @@ -53328,55 +56983,224 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Update remote config", + "summary": "List deleted dashboards", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- Send the complete configuration, not a patch: rule order is the priority, so a partial update has no unambiguous meaning.\n- Every call publishes a new version, even when the content is unchanged or `enabled` is `false`; only the 50 most recent versions are kept.\n- Call `POST /rum/application/remote-config/preview` first to check what clients would receive.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/rum/applications/rum-application-remote-config-write-update", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Dashboards Manage** (`rum`) |\n\n## Usage\n\n- Listing the trash requires the Dashboards Manage permission, unlike the live dashboard list.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-read-trash-list", "metadata": { - "sidebarTitle": "Update remote config" + "sidebarTitle": "List deleted dashboards" } } } }, - "/rum/application/update": { + "/rum/dashboard/update": { "post": { - "description": "Update selected fields of a RUM application; fields left out of the request keep their current values.", - "operationId": "rum-application-write-update", + "description": "Replace a dashboard's definition under an expected-revision check.", + "operationId": "rum-dashboard-write-update", "requestBody": { "content": { "application/json": { "example": { - "alerting": { - "channel_ids": [ - 2490121812131 + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "definition": { + "default_time_range": { + "from": "now-1h", + "to": "now" + }, + "description": "Loading time and error rate of the storefront.", + "refresh_interval": "1m", + "tabs": [ + { + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abd", + "sections": [ + { + "collapsed": false, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abe", + "panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 8, + "w": 16, + "x": 0, + "y": 4 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890ac0", + "queries": [ + { + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "draw_style": "bar", + "field": "view.loading_time", + "group_by": "view.url_path", + "limit": "20", + "scope": "view" + }, + "expr": "page:${page}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "Slowest pages by p95", + "viz_config": { + "column_options": { + "A": { + "display_name": "p95", + "threshold": { + "critical": 3000, + "mode": "higher_is_worse", + "warning": 1500 + }, + "threshold_display": "background", + "unit": "milliseconds" + }, + "view.url_path": { + "display_name": "Page", + "width_px": 320 + } + }, + "kind": "table", + "link_columns": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890ac1", + "pass_time": true, + "variable_mappings": { + "page": { + "column": "view.url_path", + "source": "row_column" + } + } + } + ], + "options": { + "dense": true + }, + "sort": [ + { + "direction": "desc", + "field": "A" + } + ] + } + } + ], + "title": "Slowest pages" + } + ], + "title": "Overview", + "top_panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 4, + "w": 8, + "x": 0, + "y": 0 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abf", + "queries": [ + { + "legend_alias": "p95 loading time", + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "field": "view.loading_time", + "scope": "view" + }, + "expr": "env:${env}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "p95 loading time", + "viz_config": { + "decimals": 0, + "kind": "stat", + "options": { + "sparkline": true + }, + "reducer": "max", + "unit": "milliseconds", + "value_fields": [ + "view.loading_time" + ] + } + } + ] + } ], - "enabled": true - }, - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "application_name": "My Web App v2", - "links": { - "enabled": true, - "systems": [ + "title": "Web performance overview", + "variables": [ { - "enabled": true, - "event_types": [ - "crash", - "error" + "default": { + "kind": "all" + }, + "kind": "custom", + "label": "Environment", + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + } ], - "icon_color": "#0F766E", - "icon_text": "S3", - "id": "s3-crash-logs", - "name": "S3 Crash Logs", - "url": "https://s3.example.com/logs?app=${application_id}&trace=${trace_id}" + "selection": { + "include_all": true, + "mode": "multi" + } + }, + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "default": { + "kind": "values", + "values": [ + "/checkout" + ] + }, + "kind": "query", + "label": "Page", + "name": "page", + "refresh": "on_dashboard_load", + "selection": { + "include_all": false, + "mode": "single" + }, + "variable_query": { + "field": "view.url_path", + "kind": "rum_field" + } } ] - } + }, + "expected_revision": 3, + "message": "Raise the p95 threshold", + "schema_version": "dashboard.v1" }, "schema": { - "$ref": "#/components/schemas/RumApplicationUpdateRequest" + "$ref": "#/components/schemas/RumDashboardUpdateRequest" } } }, @@ -53387,7 +57211,214 @@ "content": { "application/json": { "example": { - "data": {}, + "data": { + "changed": true, + "resource": { + "created_at": 1792401120000, + "created_by": { + "id": 2477033058131, + "name": "Alex Chen" + }, + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890abc", + "definition": { + "default_time_range": { + "from": "now-1h", + "to": "now" + }, + "description": "Loading time and error rate of the storefront.", + "refresh_interval": "1m", + "tabs": [ + { + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abd", + "sections": [ + { + "collapsed": false, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abe", + "panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 8, + "w": 16, + "x": 0, + "y": 4 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890ac0", + "queries": [ + { + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "draw_style": "bar", + "field": "view.loading_time", + "group_by": "view.url_path", + "limit": "20", + "scope": "view" + }, + "expr": "page:${page}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "Slowest pages by p95", + "viz_config": { + "column_options": { + "A": { + "display_name": "p95", + "threshold": { + "critical": 3000, + "mode": "higher_is_worse", + "warning": 1500 + }, + "threshold_display": "background", + "unit": "milliseconds" + }, + "view.url_path": { + "display_name": "Page", + "width_px": 320 + } + }, + "kind": "table", + "link_columns": [ + { + "dashboard_id": "0192f3a4-5b6c-7d8e-9f01-234567890ac1", + "pass_time": true, + "variable_mappings": { + "page": { + "column": "view.url_path", + "source": "row_column" + } + } + } + ], + "options": { + "dense": true + }, + "sort": [ + { + "direction": "desc", + "field": "A" + } + ] + } + } + ], + "title": "Slowest pages" + } + ], + "title": "Overview", + "top_panels": [ + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "grid": { + "h": 4, + "w": 8, + "x": 0, + "y": 0 + }, + "id": "0192f3a4-5b6c-7d8e-9f01-234567890abf", + "queries": [ + { + "legend_alias": "p95 loading time", + "query": { + "args": { + "agg": "p95", + "application_id": "qLpu24Dz4CAzWsESPbJYWA", + "field": "view.loading_time", + "scope": "view" + }, + "expr": "env:${env}", + "min_step_seconds": 60, + "mode": "range" + }, + "ref_id": "A" + } + ], + "title": "p95 loading time", + "viz_config": { + "decimals": 0, + "kind": "stat", + "options": { + "sparkline": true + }, + "reducer": "max", + "unit": "milliseconds", + "value_fields": [ + "view.loading_time" + ] + } + } + ] + } + ], + "title": "Web performance overview", + "variables": [ + { + "default": { + "kind": "all" + }, + "kind": "custom", + "label": "Environment", + "name": "env", + "options": [ + { + "text": "Production", + "value": "prod" + }, + { + "text": "Staging", + "value": "staging" + } + ], + "selection": { + "include_all": true, + "mode": "multi" + } + }, + { + "datasource_ref": { + "datasource_type": "rum", + "kind": "fixed" + }, + "default": { + "kind": "values", + "values": [ + "/checkout" + ] + }, + "kind": "query", + "label": "Page", + "name": "page", + "refresh": "on_dashboard_load", + "selection": { + "include_all": false, + "mode": "single" + }, + "variable_query": { + "field": "view.url_path", + "kind": "rum_field" + } + } + ] + }, + "revision": 4, + "schema_version": "dashboard.v1", + "updated_at": 1792404240000, + "updated_by": { + "id": 2477033058177, + "name": "Mei Lin" + } + } + }, "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, "schema": { @@ -53398,7 +57429,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RumDashboardUpdateResponse" } }, "type": "object" @@ -53418,83 +57449,55 @@ "403": { "$ref": "#/components/responses/Forbidden" }, - "429": { - "$ref": "#/components/responses/TooManyRequests" - }, - "500": { - "$ref": "#/components/responses/ServerError" - } - }, - "summary": "Update application", - "tags": [ - "RUM/Applications" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- Only fields present in the request are changed. `alerting`, `tracing` and `links` replace the whole stored object when sent; `repositories` replaces the whole list.\n- When `tracing` is sent, `open_type` (`popup` or `tab`) and an `http`/`https` `endpoint` are required even if `enabled` is `false`.\n- `links.systems[].url` must start with `http` or `https`; each system needs a `name` and at least one `event_types` entry.\n- When `alerting` is sent with `delivery_mode` `oncall`, the existing `integration_id` is kept (or one is assigned); a client-supplied `integration_id` is ignored.\n- An unknown or deleted `application_id` returns `InvalidParameter`. The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/rum/applications/rum-application-write-update", - "metadata": { - "sidebarTitle": "Update application" - } - } - } - }, - "/rum/application/webhook/test": { - "post": { - "description": "Send a sample RUM alert event to verify an application's webhook URL.", - "operationId": "rum-application-webhook-test", - "requestBody": { - "content": { - "application/json": { - "example": { - "application_id": "WoyQQ3BohkdtPivubEvE8o", - "webhook_url": "https://hooks.example.com/rum-alerts" - }, - "schema": { - "$ref": "#/components/schemas/RumWebhookTestRequest" + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } - } + }, + "description": "The dashboard does not exist. HTTP 404 `DashboardNotFound`." }, - "required": true - }, - "responses": { - "200": { + "409": { "content": { "application/json": { - "example": { - "data": { - "message": "ok", - "ok": true, - "status_code": 200 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/RumWebhookTestResponse" - } - }, - "type": "object" - } - ] + "$ref": "#/components/schemas/ErrorResponse" } } }, - "description": "Success" + "description": "The dashboard changed since `expected_revision` was read. HTTP 409 `DashboardRevisionConflict`." }, - "400": { - "$ref": "#/components/responses/BadRequest" + "410": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The dashboard is in the trash. HTTP 410 `DashboardDeleted`." }, - "401": { - "$ref": "#/components/responses/Unauthorized" + "413": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "The request body exceeds 2 MiB, the definition exceeds 1 MiB, or a count limit is exceeded. HTTP 413 `EntityTooLarge`." }, - "403": { - "$ref": "#/components/responses/Forbidden" + "422": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "`schema_version` is not `dashboard.v1`. HTTP 422 `UnsupportedSchemaVersion`." }, "429": { "$ref": "#/components/responses/TooManyRequests" @@ -53503,15 +57506,15 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Test application webhook", + "summary": "Update dashboard", "tags": [ - "RUM/Applications" + "RUM/Dashboards" ], "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Applications Manage** (`rum`) |\n\n## Usage\n\n- The URL must use `http` or `https`; on Flashduty cloud, hosts that resolve to private, loopback, link-local or reserved addresses are rejected with `InvalidParameter`.\n- The sample body has the same shape as real alert events: `account_id`, `data_source_type` (`rum.alert`), `title`, `event_severity`, `event_status`, `description`, `alert_key`, `labels`, and `event_time` (Unix seconds).\n- Each attempt times out after 10 seconds; transport errors, 5xx and 429 responses are retried up to 2 times.\n- A failed delivery still returns HTTP 200 with `ok: false` and the reason in `message`.\n- The caller must be able to edit the application: the account owner, an account admin, the application's creator, or a member of its owning team; anyone else gets `AccessDenied`.", - "href": "/en/api-reference/rum/applications/rum-application-webhook-test", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Dashboards Manage** (`rum`) |\n\n## Usage\n\n- The definition is replaced whole; there is no partial update.\n- `expected_revision` must equal the current revision, otherwise the call fails with HTTP 409 `DashboardRevisionConflict`. Re-read with `POST /rum/dashboard/get` and retry.\n- An unchanged definition returns `changed: false` and keeps the current revision.\n- Each change stores a revision (up to 20 are kept) with the optional `message`.\n- A dashboard that does not exist returns HTTP 404 `DashboardNotFound`; one in the trash returns HTTP 410 `DashboardDeleted`.\n- A body over 2 MiB, a definition over 1 MiB, or exceeding a count limit returns HTTP 413 `EntityTooLarge`; a `schema_version` other than `dashboard.v1` returns HTTP 422 `UnsupportedSchemaVersion`.\n- Applications are verified as on create.", + "href": "/en/api-reference/rum/dashboards/rum-dashboard-write-update", "metadata": { - "sidebarTitle": "Test application webhook" + "sidebarTitle": "Update dashboard" } } } @@ -71035,6 +75038,10 @@ { "name": "Monitors/Rule folders", "description": "List the monitor folder tree that dashboards and alert rules are organised in." + }, + { + "description": "Create and manage RUM custom dashboards, their revision history and the trash.", + "name": "RUM/Dashboards" } ] } diff --git a/api-reference/openapi.zh.json b/api-reference/openapi.zh.json index 34b9f4fd..ae1d059e 100644 --- a/api-reference/openapi.zh.json +++ b/api-reference/openapi.zh.json @@ -34535,46 +34535,2439 @@ "required": [ "items" ] + }, + "RumDashboardActor": { + "description": "创建或最近修改仪表盘/版本的成员。", + "properties": { + "id": { + "description": "成员 ID。", + "format": "int64", + "type": "integer" + }, + "name": { + "description": "成员名称。", + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "RumDashboardBarViz": { + "description": "由分组序列构成的分类柱状图。", + "properties": { + "kind": { + "description": "面板类型,固定为 `bar`。", + "enum": [ + "bar" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "随面板保存的自由格式显示选项,不做校验。", + "type": "object" + }, + "unit": { + "description": "面板值的展示单位,取值 `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": "展示的小数位数。", + "maximum": 15, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "category_field": { + "description": "提供分类轴的字段 key。", + "type": "string" + }, + "value_fields": { + "description": "作为柱子的字段 key。不能为空、名称不能重复;不允许使用 `frame_index` 和 `field_index`。", + "items": { + "description": "字段 key。", + "type": "string" + }, + "type": "array" + }, + "data_link": { + "$ref": "#/components/schemas/RumDashboardDataLink" + } + }, + "required": [ + "kind", + "options", + "category_field", + "value_fields" + ], + "type": "object" + }, + "RumDashboardCandidate": { + "description": "自定义变量的一个可选项。", + "properties": { + "text": { + "description": "变量栏展示的文案,为空时取 `value`,最多 1024 个字符。", + "type": "string" + }, + "value": { + "description": "替换进查询的值,1 到 1024 个字符,不能是 `$__all`。", + "type": "string" + } + }, + "required": [ + "value" + ], + "type": "object" + }, + "RumDashboardColumnOption": { + "description": "表格面板某一列的展示配置。", + "properties": { + "display_name": { + "description": "列标题,为空时取字段 key。", + "type": "string" + }, + "hidden": { + "description": "是否隐藏该列。`false` 表示不隐藏;省略表示沿用默认。", + "type": [ + "boolean", + "null" + ] + }, + "width_px": { + "description": "列宽(像素),80 到 1200。", + "type": [ + "integer", + "null" + ], + "minimum": 80, + "maximum": 1200 + }, + "unit": { + "description": "面板值的展示单位,取值 `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": "阈值绘制方式:`text` 给数值着色,`background` 给单元格着色。", + "enum": [ + "text", + "background" + ], + "type": "string" + }, + "data_link": { + "$ref": "#/components/schemas/RumDashboardDataLink" + } + }, + "type": "object" + }, + "RumDashboardCreateRequest": { + "description": "创建请求。仪表盘 ID 由调用方提供,因此用同一 ID 重试会被判为冲突,而不会建出重复仪表盘。", + "properties": { + "dashboard_id": { + "description": "要创建的仪表盘 ID,规范 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": "定义所遵循的接口 schema,必须为 `dashboard.v1`。", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "definition" + ], + "type": "object" + }, + "RumDashboardCustomVariable": { + "description": "选项为固定列表的变量。", + "properties": { + "kind": { + "description": "变量类型,固定为 `custom`。", + "enum": [ + "custom" + ], + "type": "string" + }, + "name": { + "description": "变量名,在面板查询中以 `${name}` 引用;1–64 字符,以字母或下划线开头。`app` 和以 `__` 开头的名称为保留名;变量名不能重复。", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + }, + "label": { + "description": "变量栏展示的文案,填写时为 1 到 189 个字符。", + "type": "string" + }, + "selection": { + "$ref": "#/components/schemas/RumDashboardSelectionConfig" + }, + "options": { + "description": "固定的可选项列表,1–1000 项,`value` 不能重复。", + "items": { + "$ref": "#/components/schemas/RumDashboardCandidate" + }, + "type": "array" + }, + "default": { + "$ref": "#/components/schemas/RumDashboardSelection" + } + }, + "required": [ + "kind", + "name", + "selection", + "options" + ], + "type": "object" + }, + "RumDashboardDataLink": { + "description": "从面板单元格跳转到另一个仪表盘。", + "properties": { + "dashboard_id": { + "description": "目标仪表盘 ID,规范 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": "仪表盘内的目标页签或面板 ID,设置时须为规范 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" + }, + "pass_time": { + "description": "是否把当前时间范围传过去。", + "type": "boolean" + }, + "variable_mappings": { + "additionalProperties": { + "$ref": "#/components/schemas/RumDashboardLinkMapping" + }, + "description": "目标变量名到取值映射的关系。", + "type": "object" + } + }, + "required": [ + "dashboard_id", + "pass_time", + "variable_mappings" + ], + "type": "object" + }, + "RumDashboardDatasourceRef": { + "description": "面板或查询变量读取的数据源。RUM 仪表盘只读取内置 RUM 数据源,因此该引用固定。", + "properties": { + "kind": { + "description": "引用类型,固定为 `fixed`。", + "enum": [ + "fixed" + ], + "type": "string" + }, + "datasource_type": { + "description": "数据源类型,固定为 `rum`。", + "enum": [ + "rum" + ], + "type": "string" + }, + "datasource_id": { + "description": "保留字段,内置 RUM 数据源固定为 `0`。", + "enum": [ + 0 + ], + "type": "integer" + } + }, + "required": [ + "kind", + "datasource_type" + ], + "type": "object" + }, + "RumDashboardDefinition": { + "description": "仪表盘主体:标题、默认时间范围、变量与页签。一个仪表盘最多 10 个页签、100 个面板、300 条查询。每个页签最多 30 个面板、100 条查询,固定面板与分区面板合计。", + "properties": { + "title": { + "description": "仪表盘标题,1–189 字符。", + "type": "string" + }, + "description": { + "description": "仪表盘描述,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + }, + "default_time_range": { + "$ref": "#/components/schemas/RumDashboardRelativeTimeRange" + }, + "refresh_interval": { + "description": "仪表盘自动刷新间隔,取值 `off`、`30s`、`1m`、`5m` 之一。", + "enum": [ + "off", + "30s", + "1m", + "5m" + ], + "type": "string" + }, + "variables": { + "description": "变量栏项,最多 20 个;内置的 `app` 切换不在其中声明。", + "items": { + "$ref": "#/components/schemas/RumDashboardVariable" + }, + "maxItems": 20, + "type": "array" + }, + "tabs": { + "description": "仪表盘的页签,1–10 个。", + "items": { + "$ref": "#/components/schemas/RumDashboardTab" + }, + "maxItems": 10, + "type": "array" + } + }, + "required": [ + "title", + "default_time_range", + "refresh_interval", + "variables", + "tabs" + ], + "type": "object" + }, + "RumDashboardDeleteResponse": { + "description": "把仪表盘移入回收站的结果。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "删除操作产生的版本号。恢复仪表盘时将其作为 `expected_revision` 传入。", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "revision" + ], + "type": "object" + }, + "RumDashboardFieldSort": { + "description": "表格列的排序方式。", + "properties": { + "field": { + "description": "排序使用的字段 key。", + "type": "string" + }, + "direction": { + "description": "排序方向:`asc` 或 `desc`。", + "enum": [ + "asc", + "desc" + ], + "type": "string" + } + }, + "required": [ + "field", + "direction" + ], + "type": "object" + }, + "RumDashboardGridPosition": { + "description": "面板在页签 24 列网格上的位置,`x + w` 不得超过 24。同一 `top_panels` 列表或同一分区内的面板不得重叠。", + "properties": { + "x": { + "description": "左边缘所在的列,从 0 开始,取值 0–23。", + "minimum": 0, + "type": "integer" + }, + "y": { + "description": "上边缘所在的行,从 0 开始。", + "minimum": 0, + "type": "integer" + }, + "w": { + "description": "宽度占用的列数,取值 1–24。", + "maximum": 24, + "minimum": 1, + "type": "integer" + }, + "h": { + "description": "高度占用的行数,取值 1–100。", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "x", + "y", + "w", + "h" + ], + "type": "object" + }, + "RumDashboardIDRequest": { + "description": "指定单个仪表盘的请求。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "跳转时目标仪表盘的某个变量如何取值。", + "properties": { + "source": { + "description": "取值来源:`variable`(另一个变量)、`row_column`(点击行的列),柱状面板还可为 `category`、`series`、`value`。", + "enum": [ + "variable", + "row_column", + "category", + "series", + "value" + ], + "type": "string" + }, + "column": { + "description": "`row_column` 来源的列名,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + }, + "name": { + "description": "`variable` 来源的变量名;1–64 字符,以字母或下划线开头。", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + } + }, + "required": [ + "source" + ], + "type": "object" + }, + "RumDashboardListItem": { + "description": "仪表盘列表的一行,不含定义。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "仪表盘标题。", + "type": "string" + }, + "description": { + "description": "仪表盘描述。", + "type": "string" + }, + "revision": { + "description": "当前版本号。", + "minimum": 1, + "type": "integer" + }, + "updated_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "updated_at": { + "description": "最近修改时间,Unix 毫秒时间戳。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "title", + "revision", + "updated_by", + "updated_at" + ], + "type": "object" + }, + "RumDashboardListRequest": { + "description": "列表请求。`p` 从 1 开始,`limit` 默认 20,默认按最新在前排序。", + "properties": { + "query": { + "description": "搜索文本,最多 128 个字符。按空格拆分,每个词都须出现在标题或描述中。", + "type": "string" + }, + "sort": { + "description": "排序方式,最多两个且不重复的字段;默认按 `updated_at` 倒序。", + "items": { + "$ref": "#/components/schemas/RumDashboardListSort" + }, + "maxItems": 2, + "type": "array" + }, + "p": { + "default": 1, + "description": "页码,从 1 开始,默认 1。", + "minimum": 1, + "type": "integer" + }, + "limit": { + "default": 20, + "description": "每页条数,1–100,默认 20。", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "type": "object" + }, + "RumDashboardListResponse": { + "description": "一页仪表盘。", + "properties": { + "items": { + "description": "本页的仪表盘。", + "items": { + "$ref": "#/components/schemas/RumDashboardListItem" + }, + "type": "array" + }, + "total": { + "description": "匹配查询的仪表盘总数。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "items", + "total" + ], + "type": "object" + }, + "RumDashboardListSort": { + "description": "仪表盘列表的排序方式。", + "properties": { + "field": { + "description": "`title` 或 `updated_at`。", + "enum": [ + "title", + "updated_at" + ], + "type": "string" + }, + "direction": { + "description": "`asc` 或 `desc`。", + "enum": [ + "asc", + "desc" + ], + "type": "string" + } + }, + "required": [ + "field", + "direction" + ], + "type": "object" + }, + "RumDashboardMutationRequest": { + "description": "删除或恢复请求。`expected_revision` 必须与当前版本号一致。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "调用方最后读取到的版本号,至少为 1。", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "expected_revision" + ], + "type": "object" + }, + "RumDashboardPanel": { + "description": "页签中的一个面板。", + "properties": { + "id": { + "description": "面板 ID,规范 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": "面板标题,1–189 字符。", + "type": "string" + }, + "description": { + "description": "面板描述,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + }, + "grid": { + "$ref": "#/components/schemas/RumDashboardGridPosition" + }, + "datasource_ref": { + "$ref": "#/components/schemas/RumDashboardDatasourceRef", + "description": "除 `text` 外的面板必填;`text` 面板不能传。" + }, + "queries": { + "description": "面板的查询,各自有唯一的 `ref_id`。`time_series` 和 `top_list` 可有 1 到 26 个,`table`、`stat`、`bar` 必须恰好 1 个,`text` 不能有。", + "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": "面板内的一条查询,由单个字母引用。", + "properties": { + "ref_id": { + "description": "查询引用,单个大写字母 `A`–`Z`,在面板内唯一。", + "pattern": "^[A-Z]$", + "type": "string" + }, + "query": { + "$ref": "#/components/schemas/RumDashboardQuery" + }, + "legend_alias": { + "description": "该查询序列的图例名,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + } + }, + "required": [ + "ref_id", + "query" + ], + "type": "object" + }, + "RumDashboardQuery": { + "description": "面板的一个分析问题:DQL 过滤条件,加上分析规格与所读取的应用。", + "properties": { + "mode": { + "description": "查询模式,固定为 `range`。", + "enum": [ + "range" + ], + "type": "string" + }, + "expr": { + "description": "对该范围 RUM 事件的 DQL 过滤条件,最多 16 KiB。`${name}` 必须引用仪表盘中已声明的变量;不支持 `${name:fmt}` 这类格式化写法,也不允许裸写 `$name`。", + "maxLength": 16384, + "type": "string" + }, + "args": { + "$ref": "#/components/schemas/RumDashboardQueryArgs" + }, + "min_step_seconds": { + "description": "序列的最小步长(秒),是时长而非时间戳。", + "format": "int64", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "mode", + "expr", + "args" + ], + "type": "object" + }, + "RumDashboardQueryArgs": { + "additionalProperties": false, + "description": "查询的分析规格:读取哪个范围、用什么聚合、哪个字段与如何分组。未知键会被拒绝。", + "properties": { + "scope": { + "description": "查询读取的 RUM 探索范围,取值 `session`、`view`、`resource`、`action`、`error`、`long_task`、`vital` 之一。", + "enum": [ + "session", + "view", + "resource", + "action", + "error", + "long_task", + "vital" + ], + "type": "string" + }, + "agg": { + "description": "对该范围施加的聚合方式,取值 `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": "聚合读取的字段 key。`agg` 为 `count` 时可省略。", + "type": "string" + }, + "group_by": { + "description": "分组字段,1 到 255 个字符。不能是 `session_id`、`view_id` 等事件 ID。对高基数字段分组时,`agg` 只能是 `count` 或 `sum`。", + "maxLength": 255, + "type": "string" + }, + "limit": { + "description": "返回的序列数上限,取值 `5`、`10`、`20`、`50` 之一。", + "enum": [ + "5", + "10", + "20", + "50" + ], + "type": "string" + }, + "draw_style": { + "description": "序列的绘制方式:`line` 或 `bar`。", + "enum": [ + "line", + "bar" + ], + "type": "string" + }, + "application_id": { + "description": "查询读取的应用:具体的应用 ID,或 `$app`(跟随仪表盘上选中的应用)。必填,最多 64 个字符。应用不存在或您无权读取时保存失败。", + "maxLength": 64, + "type": "string" + } + }, + "required": [ + "scope", + "agg", + "application_id" + ], + "type": "object" + }, + "RumDashboardQueryVariable": { + "description": "选项取自某个 RUM 字段取值的变量。", + "properties": { + "kind": { + "description": "变量类型,固定为 `query`。", + "enum": [ + "query" + ], + "type": "string" + }, + "name": { + "description": "变量名,在面板查询中以 `${name}` 引用;1–64 字符,以字母或下划线开头。`app` 和以 `__` 开头的名称为保留名;变量名不能重复。", + "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", + "type": "string" + }, + "label": { + "description": "变量栏展示的文案,填写时为 1 到 189 个字符;省略时控制台显示该字段的名称。", + "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": "候选值的刷新时机:`on_dashboard_load` 或 `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": "仪表盘打开时使用的时间范围。`from` 是相对偏移,`to` 固定为 `now`。", + "properties": { + "from": { + "description": "默认时间范围的相对起点,取值 `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": "范围终点,固定为 `now`。", + "enum": [ + "now" + ], + "type": "string" + } + }, + "required": [ + "from", + "to" + ], + "type": "object" + }, + "RumDashboardResource": { + "description": "仪表盘的存储形态,包含当前定义与版本号。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "定义所遵循的接口 schema,固定为 `dashboard.v1`。", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "revision": { + "description": "版本号,从 1 开始,每次变更递增。", + "minimum": 1, + "type": "integer" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + }, + "created_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "updated_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "created_at": { + "description": "创建时间,Unix 毫秒时间戳。", + "format": "int64", + "type": "integer" + }, + "updated_at": { + "description": "最近修改时间,Unix 毫秒时间戳。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "revision", + "definition", + "created_by", + "updated_by", + "created_at", + "updated_at" + ], + "type": "object" + }, + "RumDashboardRevisionGetRequest": { + "description": "查询仪表盘某个版本的请求。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "要读取的版本号,至少为 1。", + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "revision" + ], + "type": "object" + }, + "RumDashboardRevisionItem": { + "description": "版本历史中的一条,不含定义。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "版本号。", + "minimum": 1, + "type": "integer" + }, + "message": { + "description": "更新时附带的变更说明,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + }, + "actor": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "created_at": { + "description": "该版本的创建时间,Unix 毫秒时间戳。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "revision", + "actor", + "created_at" + ], + "type": "object" + }, + "RumDashboardRevisionListResponse": { + "description": "仪表盘的版本历史,最新在前,最多保留 20 个版本。", + "properties": { + "items": { + "description": "仪表盘的各个版本。", + "items": { + "$ref": "#/components/schemas/RumDashboardRevisionItem" + }, + "type": "array" + } + }, + "required": [ + "items" + ], + "type": "object" + }, + "RumDashboardRevisionResource": { + "description": "包含完整定义的一个版本。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "定义所遵循的接口 schema,固定为 `dashboard.v1`。", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "revision": { + "description": "版本号。", + "minimum": 1, + "type": "integer" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + }, + "message": { + "description": "更新时附带的变更说明,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + }, + "actor": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "created_at": { + "description": "该版本的创建时间,Unix 毫秒时间戳。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "revision", + "definition", + "actor", + "created_at" + ], + "type": "object" + }, + "RumDashboardSection": { + "description": "页签内可折叠的分区。", + "properties": { + "id": { + "description": "分区 ID,规范 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": "分区标题,1–189 字符。", + "type": "string" + }, + "description": { + "description": "分区描述,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + }, + "collapsed": { + "description": "分区是否默认折叠。", + "type": "boolean" + }, + "panels": { + "description": "分区内的面板。", + "items": { + "$ref": "#/components/schemas/RumDashboardPanel" + }, + "type": "array" + } + }, + "required": [ + "id", + "title", + "collapsed", + "panels" + ], + "type": "object" + }, + "RumDashboardSelection": { + "description": "变量的选中值。", + "properties": { + "kind": { + "description": "`values` 表示选中列出的值;`all` 表示全选,且不能带值。", + "enum": [ + "values", + "all" + ], + "type": "string" + }, + "values": { + "description": "选中的值。kind 为 `values` 时必填,kind 为 `all` 时不允许出现。不能为空、不能重复,且不能等于 `$__all`。选择模式 `mode` 为 `single` 时必须恰好一个值。", + "items": { + "description": "一个可选值。", + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "RumDashboardSelectionConfig": { + "description": "变量栏允许查看者选择值的方式。", + "properties": { + "mode": { + "description": "`single` 只允许一个值,`multi` 允许多个值。", + "enum": [ + "single", + "multi" + ], + "type": "string" + }, + "include_all": { + "description": "是否提供「全部」项;kind 为 `all` 的选择依赖它。", + "type": "boolean" + } + }, + "required": [ + "mode" + ], + "type": "object" + }, + "RumDashboardStatViz": { + "description": "归约后的单个数值。", + "properties": { + "kind": { + "description": "面板类型,固定为 `stat`。", + "enum": [ + "stat" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "随面板保存的自由格式显示选项,不做校验。", + "type": "object" + }, + "unit": { + "description": "面板值的展示单位,取值 `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": "展示的小数位数。", + "maximum": 15, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "value_fields": { + "description": "取其值归约为展示数值的字段 key。不能为空、名称不能重复;不允许使用 `frame_index` 和 `field_index`。", + "items": { + "description": "字段 key。", + "type": "string" + }, + "type": "array" + }, + "reducer": { + "description": "把多条序列归约成单个值的方式,取值 `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": "仪表盘的一个页签。最多 30 个面板、100 条查询,固定面板与分区面板合计。", + "properties": { + "id": { + "description": "页签 ID,规范 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": "页签标题,1–189 字符。", + "type": "string" + }, + "description": { + "description": "页签描述,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + }, + "top_panels": { + "description": "固定在分区上方的面板。", + "items": { + "$ref": "#/components/schemas/RumDashboardPanel" + }, + "type": "array" + }, + "sections": { + "description": "页签内的分区,最多 10 个。", + "items": { + "$ref": "#/components/schemas/RumDashboardSection" + }, + "maxItems": 10, + "type": "array" + } + }, + "required": [ + "id", + "title", + "top_panels", + "sections" + ], + "type": "object" + }, + "RumDashboardTableViz": { + "description": "分组行的表格。", + "properties": { + "kind": { + "description": "面板类型,固定为 `table`。", + "enum": [ + "table" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "随面板保存的自由格式显示选项,不做校验。", + "type": "object" + }, + "column_options": { + "additionalProperties": { + "$ref": "#/components/schemas/RumDashboardColumnOption" + }, + "description": "按列名给出的列展示配置,最多 100 列。", + "type": "object" + }, + "sort": { + "description": "表格的初始排序。", + "items": { + "$ref": "#/components/schemas/RumDashboardFieldSort" + }, + "type": "array" + }, + "link_columns": { + "description": "作为额外列渲染的跳转链接。与 `column_options` 中的 `data_link` 合计,每个表格最多 5 个。", + "items": { + "$ref": "#/components/schemas/RumDashboardDataLink" + }, + "type": "array" + } + }, + "required": [ + "kind", + "options" + ], + "type": "object" + }, + "RumDashboardTextViz": { + "description": "Markdown 文本块。", + "properties": { + "kind": { + "description": "面板类型,固定为 `text`。", + "enum": [ + "text" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "随面板保存的自由格式显示选项,不做校验。", + "type": "object" + }, + "markdown": { + "description": "Markdown 正文,最多 64 KiB。文本面板不接数据源与查询。不允许图片、原始 HTML 和 `${` 模板;链接须为 HTTPS 或以 `/` 开头。", + "maxLength": 65536, + "type": "string" + } + }, + "required": [ + "kind", + "options", + "markdown" + ], + "type": "object" + }, + "RumDashboardThreshold": { + "description": "数值面板上绘制的警告/严重阈值。`warning` 和 `critical` 至少填一个。", + "properties": { + "mode": { + "description": "哪个方向更严重:`higher_is_worse` 或 `lower_is_worse`。", + "enum": [ + "higher_is_worse", + "lower_is_worse" + ], + "type": "string" + }, + "warning": { + "description": "警告阈值。`mode` 为 `higher_is_worse` 时不得高于 `critical`,反之不得低于。", + "type": "number" + }, + "critical": { + "description": "严重阈值。", + "type": "number" + } + }, + "required": [ + "mode" + ], + "type": "object" + }, + "RumDashboardTimeSeriesViz": { + "description": "按时间绘制的折线/面积图。", + "properties": { + "kind": { + "description": "面板类型,固定为 `time_series`。", + "enum": [ + "time_series" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "随面板保存的自由格式显示选项,不做校验。", + "type": "object" + }, + "unit": { + "description": "面板值的展示单位,取值 `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": "展示的小数位数。", + "maximum": 15, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + } + }, + "required": [ + "kind", + "options" + ], + "type": "object" + }, + "RumDashboardTopListViz": { + "description": "归约后按值排序的条形榜。", + "properties": { + "kind": { + "description": "面板类型,固定为 `top_list`。", + "enum": [ + "top_list" + ], + "type": "string" + }, + "options": { + "additionalProperties": {}, + "description": "随面板保存的自由格式显示选项,不做校验。", + "type": "object" + }, + "unit": { + "description": "面板值的展示单位,取值 `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": "展示的小数位数。", + "maximum": 15, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + }, + "reducer": { + "description": "把多条序列归约成单个值的方式,取值 `last_non_null`、`min`、`max`、`mean`、`sum` 之一。", + "enum": [ + "last_non_null", + "min", + "max", + "mean", + "sum" + ], + "type": "string" + }, + "sort": { + "description": "排名方向:`asc` 或 `desc`。", + "enum": [ + "asc", + "desc" + ], + "type": "string" + }, + "limit": { + "description": "展示的条数,1–100;省略表示全部展示。", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "required": [ + "kind", + "options", + "reducer", + "sort" + ], + "type": "object" + }, + "RumDashboardTrashItem": { + "description": "回收站列表的一行。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "仪表盘标题。", + "type": "string" + }, + "description": { + "description": "仪表盘描述。", + "type": "string" + }, + "revision": { + "description": "删除操作产生的版本号。恢复仪表盘时将其作为 `expected_revision` 传入。", + "minimum": 1, + "type": "integer" + }, + "deleted_by": { + "$ref": "#/components/schemas/RumDashboardActor" + }, + "deleted_at": { + "description": "删除时间,Unix 毫秒时间戳。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "dashboard_id", + "title", + "revision", + "deleted_by", + "deleted_at" + ], + "type": "object" + }, + "RumDashboardTrashListRequest": { + "description": "回收站列表请求。`p` 从 1 开始,`limit` 默认 20,默认按删除时间倒序。", + "properties": { + "sort": { + "description": "排序方式,最多两个且不重复的字段;默认按 `deleted_at` 倒序。", + "items": { + "$ref": "#/components/schemas/RumDashboardTrashListSort" + }, + "maxItems": 2, + "type": "array" + }, + "p": { + "default": 1, + "description": "页码,从 1 开始,默认 1。", + "minimum": 1, + "type": "integer" + }, + "limit": { + "default": 20, + "description": "每页条数,1–100,默认 20。", + "maximum": 100, + "minimum": 1, + "type": "integer" + } + }, + "type": "object" + }, + "RumDashboardTrashListResponse": { + "description": "一页已删除的仪表盘。", + "properties": { + "items": { + "description": "本页已删除的仪表盘。", + "items": { + "$ref": "#/components/schemas/RumDashboardTrashItem" + }, + "type": "array" + }, + "total": { + "description": "回收站中的仪表盘总数。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "items", + "total" + ], + "type": "object" + }, + "RumDashboardTrashListSort": { + "description": "回收站列表的排序方式。", + "properties": { + "field": { + "description": "`title` 或 `deleted_at`。", + "enum": [ + "title", + "deleted_at" + ], + "type": "string" + }, + "direction": { + "description": "`asc` 或 `desc`。", + "enum": [ + "asc", + "desc" + ], + "type": "string" + } + }, + "required": [ + "field", + "direction" + ], + "type": "object" + }, + "RumDashboardUnitFields": { + "description": "显示数值的面板类型共用的数值展示配置。", + "properties": { + "unit": { + "description": "面板值的展示单位,取值 `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": "展示的小数位数。", + "maximum": 15, + "minimum": 0, + "type": "integer" + }, + "threshold": { + "$ref": "#/components/schemas/RumDashboardThreshold" + } + }, + "type": "object" + }, + "RumDashboardUpdateRequest": { + "description": "更新请求。`expected_revision` 使写入带条件:仪表盘已被他人改动时返回 `DashboardRevisionConflict`。", + "properties": { + "dashboard_id": { + "description": "仪表盘 ID,规范 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": "定义所遵循的接口 schema,必须为 `dashboard.v1`。", + "enum": [ + "dashboard.v1" + ], + "type": "string" + }, + "expected_revision": { + "description": "调用方最后读取到的版本号,至少为 1。", + "minimum": 1, + "type": "integer" + }, + "definition": { + "$ref": "#/components/schemas/RumDashboardDefinition" + }, + "message": { + "description": "随该版本保存的可选变更说明,最多 1024 字符。", + "maxLength": 1024, + "type": "string" + } + }, + "required": [ + "dashboard_id", + "schema_version", + "expected_revision", + "definition" + ], + "type": "object" + }, + "RumDashboardUpdateResponse": { + "description": "更新结果。提交的定义与已存储的一致时 `changed` 为 `false`,此时仍返回 `resource`。", + "properties": { + "changed": { + "description": "已存储的定义是否真的发生变化。", + "type": "boolean" + }, + "resource": { + "$ref": "#/components/schemas/RumDashboardResource" + } + }, + "required": [ + "changed", + "resource" + ], + "type": "object" + }, + "RumDashboardVariable": { + "description": "变量栏的一项。由 `kind` 决定结构:`custom` 带固定选项列表,`query` 读取某个 RUM 字段的取值。", + "discriminator": { + "propertyName": "kind" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/RumDashboardCustomVariable" + }, + { + "$ref": "#/components/schemas/RumDashboardQueryVariable" + } + ] + }, + "RumDashboardVariableQuery": { + "description": "查询变量从哪里取候选值。RUM 只支持列出某个 RUM 字段的取值。", + "properties": { + "kind": { + "description": "查询类型,固定为 `rum_field`。", + "enum": [ + "rum_field" + ], + "type": "string" + }, + "field": { + "description": "作为候选值的 RUM 字段 key。", + "type": "string" + } + }, + "required": [ + "kind", + "field" + ], + "type": "object" + }, + "RumDashboardVizConfig": { + "description": "面板如何渲染查询结果。由 `kind` 在 `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": "在 Flashduty 控制台 我的 → APP Key 中创建的 APP Key。可通过 query 参数 `app_key` 或请求头 `Fd-App-Key` 传入。实际可访问范围是该 APP Key 的权限范围与创建者当前角色权限的交集,请妥善保管。" + } + } + }, + "info": { + "description": "Flashduty 事件管理平台的公开 HTTP API —— 覆盖故障、通知模板、协作空间、值班排班、监控、RUM、以及平台管理。每次调用都需在 query 中携带 `app_key`,该 key 在 Flashduty 控制台 账户 → APP Key 中签发。所有响应使用统一结构:成功时为 `{ request_id, data }`,失败时为 `{ request_id, error }`。", + "title": "Flashduty 开放 API", + "version": "1.0.0" + }, + "openapi": "3.1.0", + "paths": { + "/account/info": { + "post": { + "summary": "查看主体信息", + "description": "返回当前主体(账户)的基本信息与设置。", + "operationId": "account-read-info", + "tags": [ + "平台/账户设置" + ], + "security": [ + { + "AppKeyAuth": [] + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object" + }, + "example": {} + } + } + }, + "responses": { + "200": { + "description": "成功", + "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": "查看主体信息" + }, + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 但对调用凭据有要求,见使用说明 |\n\n## 使用说明\n\n- 需要账户主体的凭据(如账户主体创建的 App Key);使用成员凭据调用会返回 `401 Unauthorized`。成员可改用 `POST /member/info`。\n- `restrictions` 仅在配置过加入限制或访问限制时返回;`mp_plat`、`mp_account_id` 仅对通过云市场开通的账户返回。", + "href": "/zh/api-reference/platform/account/account-read-info" + } + } + }, + "/alert-event/list": { + "post": { + "operationId": "alert-event-read-list", + "summary": "查询原始告警事件列表", + "description": "返回跨所有告警的原始告警事件分页列表,支持按集成、协作空间、时间范围和严重程度过滤。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `start_time` 和 `end_time` 均为必填的 Unix 时间戳(秒)。`start_time` 必须小于 `end_time`,跨度不超过 31 天。\n- 结果会根据调用方的协作空间数据访问权限进行过滤。传了 `channel_ids` 但其中没有调用方可访问的协作空间时,结果为空。\n- `severities` 为逗号分隔的列表,按 `event_severity` 匹配,如 `\"Critical,Warning\"`。取值不做校验,未知值(或 `Ok`)不会匹配任何事件。\n- 传入上次响应中的 `search_after_ctx` 获取下一页;不传时按 `p`/`limit` 页码分页,且 `p * limit` 不超过 10,000。", + "href": "/zh/api-reference/on-call/alerts/alert-event-read-list", + "metadata": { + "sidebarTitle": "查询原始告警事件列表" + } + }, + "responses": { + "200": { + "description": "成功", + "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": "查询告警事件列表", + "description": "通过游标或页码分页返回指定告警的原始事件。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 默认按最新事件优先返回;设置 `asc=true` 可按最早事件优先读取。\n- 使用上次响应中的 `search_after_ctx` 搭配 `limit` 获取下一页。\n- 也支持通过 `p` 使用页码分页,但 `p * limit` 必须在 10,000 条以内。\n- 账户中不存在的 `alert_id` 返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/alerts/alert-read-event-list", + "metadata": { + "sidebarTitle": "查询告警事件列表" + } + }, + "responses": { + "200": { + "description": "成功", + "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": "查询告警动态", + "description": "返回单条告警的动态记录(评论、状态变更、合并、静默事件),支持分页查询。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 使用 `p`(页码,从 1 开始)和 `limit`(最大 100,默认 20)进行分页。\n- 将 `asc` 设为 `true` 可按时间正序返回。\n- 使用 `types` 过滤特定动态类型(如 `a_comm`、`a_merge`)。\n- 账户中不存在的 `alert_id` 返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/alerts/alert-read-feed", + "metadata": { + "sidebarTitle": "查询告警动态" + } + }, + "responses": { + "200": { + "description": "成功", + "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": "查看告警详情", + "description": "通过告警 ID 返回单条告警的完整详情,包括关联故障和事件数量。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- `alert_id` 为 ObjectID 十六进制字符串,可从 `POST /alert/list` 或 `POST /alert-event/list` 获取。\n- 账户中不存在的 `alert_id` 返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/alerts/alert-read-info", + "metadata": { + "sidebarTitle": "查看告警详情" + } + }, + "responses": { + "200": { + "description": "成功", + "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": "查询告警列表", + "description": "返回满足过滤条件的告警列表,支持游标分页。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) 或 **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- `start_time` 和 `end_time` 为必填的 Unix 时间戳(秒),按告警的 `start_time` 过滤,跨度不超过 31 天。\n- `by_updated_at` 为 `true` 时,在 `start_time` 过滤之外再按相同区间过滤 `updated_at`,且跨度不超过 7 天。\n- `start_time` 早于账户数据保留期时会被调整为保留期起点;`end_time` 早于该起点时返回 `InvalidParameter`。\n- 传入上次响应中的 `search_after_ctx` 获取下一页;不传时按 `p`/`limit` 页码分页,且 `p * limit` 不超过 10,000。\n- `total` 最多为 1,000。`has_next_page` 不依赖 `total`:页码模式和游标模式下都准确,超过 1,000 条也一样。每个非空页都会返回最后一条告警的 `search_after_ctx`;要越过页码模式 10,000 条的上限,请传回该值继续读取。\n- 结果会根据调用方的协作空间数据访问权限进行过滤。\n- 将 `is_active` 设为 `true` 可仅返回活跃(触发中)告警;设为 `false` 返回已恢复告警。", + "href": "/zh/api-reference/on-call/alerts/alert-read-list", + "metadata": { + "sidebarTitle": "查询告警列表" + } + }, + "responses": { + "200": { + "description": "成功", + "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": "在 Flashduty 控制台 我的 → APP Key 中创建的 APP Key。可通过 query 参数 `app_key` 或请求头 `Fd-App-Key` 传入。实际可访问范围是该 APP Key 的权限范围与创建者当前角色权限的交集,请妥善保管。" - } - } - }, - "info": { - "description": "Flashduty 事件管理平台的公开 HTTP API —— 覆盖故障、通知模板、协作空间、值班排班、监控、RUM、以及平台管理。每次调用都需在 query 中携带 `app_key`,该 key 在 Flashduty 控制台 账户 → APP Key 中签发。所有响应使用统一结构:成功时为 `{ request_id, data }`,失败时为 `{ request_id, error }`。", - "title": "Flashduty 开放 API", - "version": "1.0.0" - }, - "openapi": "3.1.0", - "paths": { - "/account/info": { + "/alert/list-by-ids": { "post": { - "summary": "查看主体信息", - "description": "返回当前主体(账户)的基本信息与设置。", - "operationId": "account-read-info", + "operationId": "alert-read-list-by-ids", + "summary": "批量查询告警", + "description": "按告警 ID 一次返回多条告警详情,不分页。", "tags": [ - "平台/账户设置" + "On-call/告警管理" ], - "security": [ - { - "AppKeyAuth": [] + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 格式错误的 ID 会使请求返回 `InvalidParameter`;格式正确但账户中不存在的 ID 不会出现在 `items` 中。\n- 响应不分页:`total` 恒为 `0`,`has_next_page` 恒为 `false`,不返回 `search_after_ctx`。", + "href": "/zh/api-reference/on-call/alerts/alert-read-list-by-ids", + "metadata": { + "sidebarTitle": "批量查询告警" + } + }, + "responses": { + "200": { + "description": "成功", + "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" + ] + } + } } + } + } + }, + "/alert/merge": { + "post": { + "operationId": "alert-write-merge", + "summary": "将告警合并到故障", + "description": "将一条或多条告警移入已有故障,并关闭因此变空的来源故障。", + "tags": [ + "On-call/告警管理" ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `alert_ids` 中的每个 ID 和 `incident_id` 都必须属于调用方账户,不存在的 ID 返回 `InvalidParameter`。\n- 已在目标故障中的告警会被跳过。来源故障合并后若不再有告警,会被关闭。\n- `title` 和 `owner_id` 仅在与目标故障当前值不同时才会更新。\n- 同一账户同一时间只处理一个故障变更,并发调用返回 `RequestTooFrequently`。", + "href": "/zh/api-reference/on-call/alerts/alert-write-merge", + "metadata": { + "sidebarTitle": "将告警合并到故障" + } + }, + "responses": { + "200": { + "description": "成功", + "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": { - "type": "object" + "$ref": "#/components/schemas/AlertMergeRequest" }, - "example": {} + "example": { + "alert_ids": [ + "663a1b2c3d4e5f6789abcdef" + ], + "incident_id": "663a000000000000deadbeef" + } } } + } + } + }, + "/alert/pipeline/info": { + "post": { + "operationId": "alert-read-pipeline-info", + "summary": "查看告警处理规则", + "description": "返回指定集成的告警处理规则配置。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 该集成未配置告警处理规则时,响应只包含 `request_id`,不返回 `data` 字段。\n- `integration_id` 可以是账户中任意账户级或协作空间专属集成;不存在的 ID 返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/alerts/alert-read-pipeline-info", + "metadata": { + "sidebarTitle": "查看告警处理规则" + } }, "responses": { "200": { @@ -34590,7 +36983,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AccountInfo" + "$ref": "#/components/schemas/AlertPipelineItem" } } } @@ -34599,28 +36992,148 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "account_id": 1001, - "account_name": "acme", - "domain": "acme", - "extra_domains": [ - "acme-corp" + "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" + } + } ], - "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 + "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": "批量查询告警处理规则", + "description": "返回多个集成的告警处理规则配置。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- `integration_ids` 中每个 ID 都必须是账户中的集成;只要有一个不存在,整个请求返回 `InvalidParameter`。\n- `items` 中每个已配置规则的集成对应一项,未配置的集成不出现。", + "href": "/zh/api-reference/on-call/alerts/alert-read-pipeline-list", + "metadata": { + "sidebarTitle": "批量查询告警处理规则" + } + }, + "responses": { + "200": { + "description": "成功", + "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 + } + ] } } } @@ -34642,28 +37155,133 @@ "$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": "创建或更新告警处理规则", + "description": "为集成设置告警处理规则,将完全替换已有配置。", + "tags": [ + "On-call/告警管理" + ], "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 用 `rules` 整体替换该集成的规则列表;传空数组会清空所有规则。最多 50 条。\n- 规则按数组顺序作用于该集成收到的每个事件,在事件生成告警之前执行;`alert_drop` 或命中的 `alert_inhibit` 会丢弃事件并停止后续处理。\n- `integration_id` 可以是账户级集成,也可以是协作空间专属集成;账户中不存在的 ID 返回 `InvalidParameter`。\n- 写操作还需对象权限:主体账户、管理员、集成创建者或其所属团队成员可操作(协作空间专属集成看协作空间所属团队);未设置团队时,拥有接口权限的调用方均可操作。\n- `alert_inhibit` 规则需要 Standard 及以上套餐,否则返回 `NoLicense`。\n- 成功时响应只包含 `request_id`,不返回 `data` 字段。\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。", + "href": "/zh/api-reference/on-call/alerts/alert-write-pipeline-upsert", "metadata": { - "sidebarTitle": "查看主体信息" + "sidebarTitle": "创建或更新告警处理规则" + } + }, + "responses": { + "200": { + "description": "成功", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + } + } + } }, - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 但对调用凭据有要求,见使用说明 |\n\n## 使用说明\n\n- 需要账户主体的凭据(如账户主体创建的 App Key);使用成员凭据调用会返回 `401 Unauthorized`。成员可改用 `POST /member/info`。\n- `restrictions` 仅在配置过加入限制或访问限制时返回;`mp_plat`、`mp_account_id` 仅对通过云市场开通的账户返回。", - "href": "/zh/api-reference/platform/account/account-read-info" + "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/AlertPipelineUpsertRequest" + }, + "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" + } + } + ] + } + } + } } } }, - "/alert-event/list": { + "/audit/operation/list": { "post": { - "operationId": "alert-event-read-list", - "summary": "查询原始告警事件列表", - "description": "返回跨所有告警的原始告警事件分页列表,支持按集成、协作空间、时间范围和严重程度过滤。", + "operationId": "audit-read-operation-list", + "summary": "查看事件类型列表", + "description": "返回所有会记录到审计日志中的操作名称,可用于 `operations` 过滤参数。", "tags": [ - "On-call/告警管理" + "平台/审计日志" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `start_time` 和 `end_time` 均为必填的 Unix 时间戳(秒)。`start_time` 必须小于 `end_time`,跨度不超过 31 天。\n- 结果会根据调用方的协作空间数据访问权限进行过滤。传了 `channel_ids` 但其中没有调用方可访问的协作空间时,结果为空。\n- `severities` 为逗号分隔的列表,按 `event_severity` 匹配,如 `\"Critical,Warning\"`。取值不做校验,未知值(或 `Ok`)不会匹配任何事件。\n- 传入上次响应中的 `search_after_ctx` 获取下一页;不传时按 `p`/`limit` 页码分页,且 `p * limit` 不超过 10,000。", - "href": "/zh/api-reference/on-call/alerts/alert-event-read-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **审计查看**(`organization`) |\n\n## 使用说明\n\n- 将响应中的 `name` 值作为 `POST /audit/search` 的 `operations` 过滤值。\n- `name_cn` 是控制台中显示的中文标签,不随请求语言变化;`name` 是用于过滤的稳定值。", + "href": "/zh/api-reference/platform/audit-logs/audit-read-operation-list", "metadata": { - "sidebarTitle": "查询原始告警事件列表" + "sidebarTitle": "查看事件类型列表" } }, "responses": { @@ -34680,7 +37298,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertEventGlobalListResponse" + "$ref": "#/components/schemas/AuditOperationListResponse" } } } @@ -34689,18 +37307,20 @@ "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 + "name": "template:write:create", + "name_cn": "创建模板" + }, + { + "name": "template:write:delete", + "name_cn": "删除模板" + }, + { + "name": "incident:write:acknowledge", + "name_cn": "认领故障" } - ], - "search_after_ctx": "663a1b2c3d4e5f6789abc001" + ] } } } @@ -34727,32 +37347,27 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertEventGlobalListRequest" + "$ref": "#/components/schemas/AuditOperationListRequest" }, - "example": { - "start_time": 1712620800, - "end_time": 1712707200, - "limit": 20, - "severities": "Critical" - } + "example": {} } } } } }, - "/alert/event/list": { + "/audit/search": { "post": { - "operationId": "alert-read-event-list", - "summary": "查询告警事件列表", - "description": "通过游标或页码分页返回指定告警的原始事件。", + "operationId": "audit-read-search", + "summary": "检索审计日志", + "description": "按时间范围返回游标分页的操作审计日志列表。", "tags": [ - "On-call/告警管理" + "平台/审计日志" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 默认按最新事件优先返回;设置 `asc=true` 可按最早事件优先读取。\n- 使用上次响应中的 `search_after_ctx` 搭配 `limit` 获取下一页。\n- 也支持通过 `p` 使用页码分页,但 `p * limit` 必须在 10,000 条以内。\n- 账户中不存在的 `alert_id` 返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/alerts/alert-read-event-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **审计查看**(`organization`) |\n\n## 使用说明\n\n- 必须指定时间范围,跨度最长 90 天。`start_time` 和 `end_time` 均为 Unix 时间戳(**秒**)。\n- 使用上一次响应中的 `search_after_ctx` 获取下一页。该游标是不透明的,请勿自行构造。\n- 可查询的保留期取决于账户的 License。超出保留期的查询会直接返回空结果,而不是报错。\n- 建议显式传 `limit`(1–99)以便稳定分页;不传或为 0 时由服务端决定每页条数,可能一次返回全部结果。结果按时间倒序返回。", + "href": "/zh/api-reference/platform/audit-logs/audit-read-search", "metadata": { - "sidebarTitle": "查询告警事件列表" + "sidebarTitle": "检索审计日志" } }, "responses": { @@ -34769,7 +37384,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertEventListResponse" + "$ref": "#/components/schemas/AuditSearchResponse" } } } @@ -34778,20 +37393,25 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 57, - "has_next_page": true, - "search_after_ctx": "663a1b2c3d4e5f6789abc001", - "items": [ + "total": 2, + "search_after_ctx": "", + "docs": [ { - "event_id": "663a1b2c3d4e5f6789abc001", - "alert_id": "663a1b2c3d4e5f6789abcdef", - "title": "CPU usage > 90%", - "event_severity": "Critical", - "event_status": "Critical", - "event_time": 1712650000, - "labels": { - "host": "web-01" - } + "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 } ] } @@ -34820,30 +37440,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertEventListRequest" + "$ref": "#/components/schemas/AuditSearchRequest" }, "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "limit": 20 + "start_time": 1712620800, + "end_time": 1712707200, + "limit": 20, + "operations": [ + "template:write:create", + "template:write:delete" + ] } } } } } }, - "/alert/feed": { + "/calendar/create": { "post": { - "operationId": "alert-read-feed", - "summary": "查询告警动态", - "description": "返回单条告警的动态记录(评论、状态变更、合并、静默事件),支持分页查询。", + "operationId": "calendarCreate", + "summary": "创建服务日历", + "description": "创建个人服务日历,并设置每周工作日与关联的节假日日历。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 使用 `p`(页码,从 1 开始)和 `limit`(最大 100,默认 20)进行分页。\n- 将 `asc` 设为 `true` 可按时间正序返回。\n- 使用 `types` 过滤特定动态类型(如 `a_comm`、`a_merge`)。\n- 账户中不存在的 `alert_id` 返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/alerts/alert-read-feed", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 每个账户最多 5 个日历:账户已有 5 个日历后,任何成员的创建请求都返回 `InvalidParameter`。\n- `cal_name` 在账户内必须唯一,`timezone` 必须是合法的 IANA 时区,非零 `team_id` 必须是账户中的团队,否则返回 `InvalidParameter`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/calendars/calendar-create", "metadata": { - "sidebarTitle": "查询告警动态" + "sidebarTitle": "创建服务日历" } }, "responses": { @@ -34860,7 +37485,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertFeedResponse" + "$ref": "#/components/schemas/CalendarCreateResponse" } } } @@ -34869,20 +37494,8 @@ "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 - } - ] + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "cal_name": "API Test Calendar" } } } @@ -34909,31 +37522,38 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertFeedRequest" + "$ref": "#/components/schemas/CalendarCreateRequest" }, "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "limit": 20, - "asc": false + "cal_name": "Production On-Call Calendar", + "description": "Calendar for production on-call team", + "timezone": "Asia/Shanghai", + "workdays": [ + 1, + 2, + 3, + 4, + 5 + ] } } } } } }, - "/alert/info": { + "/calendar/delete": { "post": { - "operationId": "alert-read-info", - "summary": "查看告警详情", - "description": "通过告警 ID 返回单条告警的完整详情,包括关联故障和事件数量。", + "operationId": "calendarDelete", + "summary": "删除服务日历", + "description": "删除个人服务日历及其事件,前提是没有策略引用它。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- `alert_id` 为 ObjectID 十六进制字符串,可从 `POST /alert/list` 或 `POST /alert-event/list` 获取。\n- 账户中不存在的 `alert_id` 返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/alerts/alert-read-info", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 日历仍被分派策略或静默策略使用时,返回 HTTP 400,`error.code` 为 `ReferenceExist`,`data.refs` 列出引用方。\n- 日历自有的事件会一并删除。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/calendars/calendar-delete", "metadata": { - "sidebarTitle": "查看告警详情" + "sidebarTitle": "删除服务日历" } }, "responses": { @@ -34950,7 +37570,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertItem" + "$ref": "#/components/schemas/CalendarEmptyObject" } } } @@ -34958,14 +37578,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 +37604,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertInfoRequest" + "$ref": "#/components/schemas/CalendarIDRequest" }, "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef" + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM" } } } } } }, - "/alert/list": { + "/calendar/event/delete": { "post": { - "operationId": "alert-read-list", - "summary": "查询告警列表", - "description": "返回满足过滤条件的告警列表,支持游标分页。", + "operationId": "calEventDelete", + "summary": "删除日历事件", + "description": "按 ID 删除个人日历的一个事件,或清除该日历自有事件在某个日期范围内的部分。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) 或 **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- `start_time` 和 `end_time` 为必填的 Unix 时间戳(秒),按告警的 `start_time` 过滤,跨度不超过 31 天。\n- `by_updated_at` 为 `true` 时,在 `start_time` 过滤之外再按相同区间过滤 `updated_at`,且跨度不超过 7 天。\n- `start_time` 早于账户数据保留期时会被调整为保留期起点;`end_time` 早于该起点时返回 `InvalidParameter`。\n- 传入上次响应中的 `search_after_ctx` 获取下一页;不传时按 `p`/`limit` 页码分页,且 `p * limit` 不超过 10,000。\n- `total` 最多为 1,000。`has_next_page` 不依赖 `total`:页码模式和游标模式下都准确,超过 1,000 条也一样。每个非空页都会返回最后一条告警的 `search_after_ctx`;要越过页码模式 10,000 条的上限,请传回该值继续读取。\n- 结果会根据调用方的协作空间数据访问权限进行过滤。\n- 将 `is_active` 设为 `true` 可仅返回活跃(触发中)告警;设为 `false` 返回已恢复告警。", - "href": "/zh/api-reference/on-call/alerts/alert-read-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 传 `event_id`,或同时传 `start_at` 与 `end_at`(格式 `YYYY-MM-DD`,覆盖 [`start_at`, `end_at`));其他组合返回 `InvalidParameter`。\n- 清除后这些日期回到关联节假日日历和每周工作日设置的判定。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/calendars/cal-event-delete", "metadata": { - "sidebarTitle": "查询告警列表" + "sidebarTitle": "删除日历事件" } }, "responses": { @@ -35030,7 +37643,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertListResponse" + "$ref": "#/components/schemas/CalendarEmptyObject" } } } @@ -35038,35 +37651,7 @@ }, "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" - } + "data": {} } } } @@ -35092,32 +37677,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertListRequest" + "$ref": "#/components/schemas/CalEventIDRequest" }, "example": { - "start_time": 1712620800, - "end_time": 1712707200, - "limit": 20, - "is_active": true + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4" } } } } } }, - "/alert/list-by-ids": { + "/calendar/event/list": { "post": { - "operationId": "alert-read-list-by-ids", - "summary": "批量查询告警", - "description": "按告警 ID 一次返回多条告警详情,不分页。", + "operationId": "calEventList", + "summary": "查询日历事件列表", + "description": "返回个人日历在指定年、月或日内的事件,以及每一天的判定结果。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 格式错误的 ID 会使请求返回 `InvalidParameter`;格式正确但账户中不存在的 ID 不会出现在 `items` 中。\n- 响应不分页:`total` 恒为 `0`,`has_next_page` 恒为 `false`,不返回 `search_after_ctx`。", - "href": "/zh/api-reference/on-call/alerts/alert-read-list-by-ids", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `year` 默认为当前年份;不传 `month` 时返回整年,传 `day` 时必须同时传 `month`。\n- `items` 合并了日历自有事件(ID 为 `cale.*`)、设置了 `workdays` 时按非工作日逐日生成的 `non_work.YYYYMMDD` 条目,以及关联节假日日历的事件;`total` 统计全部条目。\n- `days` 给出范围内每一天的判定结果。\n- 仅支持个人日历(`cal_id` 以 `cal.` 开头),其他 ID 返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/calendars/cal-event-list", "metadata": { - "sidebarTitle": "批量查询告警" + "sidebarTitle": "查询日历事件列表" } }, "responses": { @@ -35134,7 +37717,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertListResponse" + "$ref": "#/components/schemas/CalEventListResponse" } } } @@ -35143,14 +37726,55 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 0, - "has_next_page": false, "items": [ { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "title": "CPU usage > 90%" + "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 + } + } } } } @@ -35177,31 +37801,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertListByIDsRequest" + "$ref": "#/components/schemas/CalEventListRequest" }, "example": { - "alert_ids": [ - "663a1b2c3d4e5f6789abcdef" - ] + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "year": 2024, + "month": 5 } } } } } }, - "/alert/merge": { + "/calendar/event/upsert": { "post": { - "operationId": "alert-write-merge", - "summary": "将告警合并到故障", - "description": "将一条或多条告警移入已有故障,并关闭因此变空的来源故障。", + "operationId": "calEventUpsert", + "summary": "创建或更新日历事件", + "description": "创建或更新个人日历自有的事件:休息日或工作日覆盖。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `alert_ids` 中的每个 ID 和 `incident_id` 都必须属于调用方账户,不存在的 ID 返回 `InvalidParameter`。\n- 已在目标故障中的告警会被跳过。来源故障合并后若不再有告警,会被关闭。\n- `title` 和 `owner_id` 仅在与目标故障当前值不同时才会更新。\n- 同一账户同一时间只处理一个故障变更,并发调用返回 `RequestTooFrequently`。", - "href": "/zh/api-reference/on-call/alerts/alert-write-merge", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 事件覆盖 [`start_at`, `end_at`) 这些日期,格式为 `YYYY-MM-DD`;`end_at` 必须晚于 `start_at`。\n- 不传 `event_id` 时创建新事件;传入的 `event_id` 必须是该日历已有的事件。\n- 写入时会把该日历自己的其他事件从这些日期上移除:完全落在范围内的事件被删除,部分重叠的被截短,跨越整个范围的被拆成两段,因此这些日期以最后一次写入为准。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/calendars/cal-event-upsert", "metadata": { - "sidebarTitle": "将告警合并到故障" + "sidebarTitle": "创建或更新日历事件" } }, "responses": { @@ -35218,7 +37842,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyObject" + "$ref": "#/components/schemas/CalEventUpsertResponse" } } } @@ -35226,7 +37850,11 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", + "summary": "Test Holiday" + } } } } @@ -35252,32 +37880,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertMergeRequest" + "$ref": "#/components/schemas/CalEventUpsertRequest" }, "example": { - "alert_ids": [ - "663a1b2c3d4e5f6789abcdef" - ], - "incident_id": "663a000000000000deadbeef" + "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" } } } } } }, - "/alert/pipeline/info": { + "/calendar/info": { "post": { - "operationId": "alert-read-pipeline-info", - "summary": "查看告警处理规则", - "description": "返回指定集成的告警处理规则配置。", + "operationId": "calendarInfo", + "summary": "获取服务日历详情", + "description": "按 ID 返回账户中一个服务日历的详情。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 该集成未配置告警处理规则时,响应只包含 `request_id`,不返回 `data` 字段。\n- `integration_id` 可以是账户中任意账户级或协作空间专属集成;不存在的 ID 返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/alerts/alert-read-pipeline-info", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不存在的 `cal_id` 返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/calendars/calendar-info", "metadata": { - "sidebarTitle": "查看告警处理规则" + "sidebarTitle": "获取服务日历详情" } }, "responses": { @@ -35294,7 +37924,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertPipelineItem" + "$ref": "#/components/schemas/CalendarItem" } } } @@ -35303,36 +37933,27 @@ "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" - } - } + "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 ], - "status": "enabled", - "creator_id": 80011, - "updated_by": 80011, - "created_at": 1710000000, - "updated_at": 1712000000 + "created_at": 1702455630, + "updated_at": 1775529526, + "creator_id": 2476444212131, + "updated_by": 3790925372131, + "status": "enabled" } } } @@ -35359,29 +37980,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertPipelineInfoRequest" + "$ref": "#/components/schemas/CalendarIDRequest" }, "example": { - "integration_id": 10001 + "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg" } } } } } }, - "/alert/pipeline/list": { + "/calendar/list": { "post": { - "operationId": "alert-read-pipeline-list", - "summary": "批量查询告警处理规则", - "description": "返回多个集成的告警处理规则配置。", + "operationId": "calendarList", + "summary": "查询服务日历列表", + "description": "返回当前账户可见的服务日历列表。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- `integration_ids` 中每个 ID 都必须是账户中的集成;只要有一个不存在,整个请求返回 `InvalidParameter`。\n- `items` 中每个已配置规则的集成对应一项,未配置的集成不出现。", - "href": "/zh/api-reference/on-call/alerts/alert-read-pipeline-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不传 `kind` 时返回个人日历。`region.official.holiday` 返回公共节假日日历,默认按调用方语言区域过滤,`no_locale` 为 `true` 时不过滤;其 `cal_id` 可填入 `extra_cal_ids`。\n- 列表不分页,`total` 等于返回的条目数。", + "href": "/zh/api-reference/on-call/calendars/calendar-list", "metadata": { - "sidebarTitle": "批量查询告警处理规则" + "sidebarTitle": "查询服务日历列表" } }, "responses": { @@ -35398,7 +38019,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertPipelineListResponse" + "$ref": "#/components/schemas/CalendarListResponse" } } } @@ -35409,42 +38030,47 @@ "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" - ] - } - ] - } - } + "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 ], - "status": "enabled", - "creator_id": 80011, - "updated_by": 80011, - "created_at": 1710000000, - "updated_at": 1712000000 + "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 } } } @@ -35471,32 +38097,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertPipelineListRequest" + "$ref": "#/components/schemas/CalendarListRequest" }, "example": { - "integration_ids": [ - 10001, - 10002 - ] + "kind": "personal" } } } } } }, - "/alert/pipeline/upsert": { + "/calendar/update": { "post": { - "operationId": "alert-write-pipeline-upsert", - "summary": "创建或更新告警处理规则", - "description": "为集成设置告警处理规则,将完全替换已有配置。", + "operationId": "calendarUpdate", + "summary": "更新服务日历", + "description": "更新个人服务日历,仅修改传入的字段。", "tags": [ - "On-call/告警管理" + "On-call/日历管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 用 `rules` 整体替换该集成的规则列表;传空数组会清空所有规则。最多 50 条。\n- 规则按数组顺序作用于该集成收到的每个事件,在事件生成告警之前执行;`alert_drop` 或命中的 `alert_inhibit` 会丢弃事件并停止后续处理。\n- `integration_id` 可以是账户级集成,也可以是协作空间专属集成;账户中不存在的 ID 返回 `InvalidParameter`。\n- 写操作还需对象权限:主体账户、管理员、集成创建者或其所属团队成员可操作(协作空间专属集成看协作空间所属团队);未设置团队时,拥有接口权限的调用方均可操作。\n- `alert_inhibit` 规则需要 Standard 及以上套餐,否则返回 `NoLicense`。\n- 成功时响应只包含 `request_id`,不返回 `data` 字段。\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。", - "href": "/zh/api-reference/on-call/alerts/alert-write-pipeline-upsert", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 除 `cal_id` 外至少传一个字段,否则返回 `InvalidParameter`。\n- 传入 `workdays` 或 `extra_cal_ids` 会整体替换原列表(空数组即清空);`team_id: 0` 表示取消团队归属。\n- `cal_name` 在账户内必须唯一。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 成功时响应只包含 `request_id`,不返回 `data` 字段。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/calendars/calendar-update", "metadata": { - "sidebarTitle": "创建或更新告警处理规则" + "sidebarTitle": "更新服务日历" } }, "responses": { @@ -35513,7 +38136,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/CalendarEmptyObject" } } } @@ -35546,33 +38169,18 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AlertPipelineUpsertRequest" + "$ref": "#/components/schemas/CalendarUpdateRequest" }, "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" - } - } + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "cal_name": "Production On-Call Calendar (Updated)", + "timezone": "America/New_York", + "workdays": [ + 1, + 2, + 3, + 4, + 5 ] } } @@ -35580,19 +38188,19 @@ } } }, - "/audit/operation/list": { + "/change/list": { "post": { - "operationId": "audit-read-operation-list", - "summary": "查看事件类型列表", - "description": "返回所有会记录到审计日志中的操作名称,可用于 `operations` 过滤参数。", + "operationId": "change-read-list", + "summary": "查询变更列表", + "description": "在指定时间窗口内查询变更记录,支持过滤、搜索与分页。", "tags": [ - "平台/审计日志" + "On-call/变更管理" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **审计查看**(`organization`) |\n\n## 使用说明\n\n- 将响应中的 `name` 值作为 `POST /audit/search` 的 `operations` 过滤值。\n- `name_cn` 是控制台中显示的中文标签,不随请求语言变化;`name` 是用于过滤的稳定值。", - "href": "/zh/api-reference/platform/audit-logs/audit-read-operation-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `start_time` 和 `end_time` 均为必填:`start_time` 必须小于 `end_time`,且时间跨度不超过 31 天。\n- 变更的 `[start_time, last_time]` 区间与查询时间窗有重叠即视为匹配。\n- 将 `include_events` 设为 `true` 可在 `events` 中附带每个变更的原始变更事件。", + "href": "/zh/api-reference/on-call/changes/change-read-list", "metadata": { - "sidebarTitle": "查看事件类型列表" + "sidebarTitle": "查询变更列表" } }, "responses": { @@ -35609,7 +38217,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AuditOperationListResponse" + "$ref": "#/components/schemas/ListChangeResponse" } } } @@ -35618,18 +38226,29 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { + "total": 1, + "has_next_page": false, "items": [ { - "name": "template:write:create", - "name_cn": "创建模板" - }, - { - "name": "template:write:delete", - "name_cn": "删除模板" - }, - { - "name": "incident:write:acknowledge", - "name_cn": "认领故障" + "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" } ] } @@ -35658,27 +38277,38 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AuditOperationListRequest" + "$ref": "#/components/schemas/ListChangeRequest" }, - "example": {} + "example": { + "start_time": 1716960000, + "end_time": 1717046400, + "p": 1, + "limit": 10, + "integration_ids": [ + 362 + ], + "orderby": "start_time", + "asc": false, + "include_events": false + } } } } } }, - "/audit/search": { + "/channel/create": { "post": { - "operationId": "audit-read-search", - "summary": "检索审计日志", - "description": "按时间范围返回游标分页的操作审计日志列表。", + "operationId": "channelCreate", + "summary": "创建协作空间", + "description": "创建协作空间,可同时创建默认分派策略和协作空间专属集成。", "tags": [ - "平台/审计日志" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **审计查看**(`organization`) |\n\n## 使用说明\n\n- 必须指定时间范围,跨度最长 90 天。`start_time` 和 `end_time` 均为 Unix 时间戳(**秒**)。\n- 使用上一次响应中的 `search_after_ctx` 获取下一页。该游标是不透明的,请勿自行构造。\n- 可查询的保留期取决于账户的 License。超出保留期的查询会直接返回空结果,而不是报错。\n- 建议显式传 `limit`(1–99)以便稳定分页;不传或为 0 时由服务端决定每页条数,可能一次返回全部结果。结果按时间倒序返回。", - "href": "/zh/api-reference/platform/audit-logs/audit-read-search", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- `channel_name` 在账户内必须唯一,重名返回 `InvalidParameter`。\n- `group.method` 为 `p` 需要 Standard 及以上许可证,为 `i` 需要 Pro 许可证。超过当前套餐的协作空间数量上限同样返回 `NoLicense`。\n- 传入 `escalate_rule` 时,会同时创建一条名为 `Default` 的已启用分派策略,只有一个环节,对 `escalate_rule.target` 通知一次。\n- `plugin_ids` 中的每个 ID 会创建一个该类型的协作空间专属集成,集成名称为该类型名称。\n- `is_external_report_enabled` 为 `true` 时,响应中会额外返回 `external_report_token`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-create", "metadata": { - "sidebarTitle": "检索审计日志" + "sidebarTitle": "创建协作空间" } }, "responses": { @@ -35695,7 +38325,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AuditSearchResponse" + "$ref": "#/components/schemas/ChannelCreateResponse" } } } @@ -35704,27 +38334,8 @@ "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 - } - ] + "channel_id": 6294542005131, + "channel_name": "Production Alerts" } } } @@ -35751,35 +38362,43 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/AuditSearchRequest" + "$ref": "#/components/schemas/CreateChannelRequest" }, "example": { - "start_time": 1712620800, - "end_time": 1712707200, - "limit": 20, - "operations": [ - "template:write:create", - "template:write:delete" - ] + "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" } } } } } }, - "/calendar/create": { + "/channel/delete": { "post": { - "operationId": "calendarCreate", - "summary": "创建服务日历", - "description": "创建个人服务日历,并设置每周工作日与关联的节假日日历。", + "operationId": "channelDelete", + "summary": "删除协作空间", + "description": "删除已禁用的协作空间,并一并删除其下的策略和协作空间专属集成。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 每个账户最多 5 个日历:账户已有 5 个日历后,任何成员的创建请求都返回 `InvalidParameter`。\n- `cal_name` 在账户内必须唯一,`timezone` 必须是合法的 IANA 时区,非零 `team_id` 必须是账户中的团队,否则返回 `InvalidParameter`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/calendars/calendar-create", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的协作空间可删除,其他状态返回 `InvalidParameter`。\n- 若仍有共享集成的路由规则(任一 case 或默认分支)指向该协作空间,返回 HTTP 400,`error.code` 为 `ReferenceExist`,`data.refs` 列出引用它的集成。请先通过 `POST /route/upsert` 把它从这些路由中移除。\n- 协作空间下的分派、静默、排除、抑制和订阅策略以及专属集成全部删除。协作空间本身为软删除:`POST /channel/info` 仍可查到,`status` 为 `deleted`。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-delete", "metadata": { - "sidebarTitle": "创建服务日历" + "sidebarTitle": "删除协作空间" } }, "responses": { @@ -35796,7 +38415,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -35804,10 +38423,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "cal_name": "API Test Calendar" - } + "data": {} } } } @@ -35833,38 +38449,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/disable": { "post": { - "operationId": "calendarDelete", - "summary": "删除服务日历", - "description": "删除个人服务日历及其事件,前提是没有策略引用它。", + "operationId": "channelDisable", + "summary": "禁用协作空间", + "description": "禁用协作空间;禁用期间新进入的告警事件全部丢弃。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 日历仍被分派策略或静默策略使用时,返回 HTTP 400,`error.code` 为 `ReferenceExist`,`data.refs` 列出引用方。\n- 日历自有的事件会一并删除。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/calendars/calendar-delete", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的协作空间可禁用,其他状态返回 `InvalidParameter`。\n- 策略与集成均保留。告警处理链路最长约一分钟后才感知到新状态。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-disable", "metadata": { - "sidebarTitle": "删除服务日历" + "sidebarTitle": "禁用协作空间" } }, "responses": { @@ -35881,7 +38488,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -35915,29 +38522,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarIDRequest" + "$ref": "#/components/schemas/ChannelIDRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM" + "channel_id": 3521074710131 } } } } } }, - "/calendar/event/delete": { + "/channel/enable": { "post": { - "operationId": "calEventDelete", - "summary": "删除日历事件", - "description": "按 ID 删除个人日历的一个事件,或清除该日历自有事件在某个日期范围内的部分。", + "operationId": "channelEnable", + "summary": "启用协作空间", + "description": "启用已禁用的协作空间,使其重新处理新的告警事件。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 传 `event_id`,或同时传 `start_at` 与 `end_at`(格式 `YYYY-MM-DD`,覆盖 [`start_at`, `end_at`));其他组合返回 `InvalidParameter`。\n- 清除后这些日期回到关联节假日日历和每周工作日设置的判定。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/calendars/cal-event-delete", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的协作空间可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-enable", "metadata": { - "sidebarTitle": "删除日历事件" + "sidebarTitle": "启用协作空间" } }, "responses": { @@ -35954,7 +38561,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -35988,30 +38595,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalEventIDRequest" + "$ref": "#/components/schemas/ChannelIDRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4" + "channel_id": 3521074710131 } } } } } }, - "/calendar/event/list": { + "/channel/escalate/rule/create": { "post": { - "operationId": "calEventList", - "summary": "查询日历事件列表", - "description": "返回个人日历在指定年、月或日内的事件,以及每一天的判定结果。", + "operationId": "channelEscalateRuleCreate", + "summary": "创建分派策略", + "description": "创建分派策略,决定协作空间的故障通知谁、如何通知。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `year` 默认为当前年份;不传 `month` 时返回整年,传 `day` 时必须同时传 `month`。\n- `items` 合并了日历自有事件(ID 为 `cale.*`)、设置了 `workdays` 时按非工作日逐日生成的 `non_work.YYYYMMDD` 条目,以及关联节假日日历的事件;`total` 统计全部条目。\n- `days` 给出范围内每一天的判定结果。\n- 仅支持个人日历(`cal_id` 以 `cal.` 开头),其他 ID 返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/calendars/cal-event-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 策略按 `priority` 从小到大匹配,第一条启用且 `time_filters`、`filters` 都命中新故障的策略负责该故障,其后的策略不再匹配。不传 `priority` 时排在现有策略之后。\n- `template_id` 必须是已存在的通知模板,`person_ids` 中的成员必须存在,`team_ids` 中的团队必须有成员,否则返回 `InvalidParameter`。\n- 新建的策略为 `enabled` 状态。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-create", "metadata": { - "sidebarTitle": "查询日历事件列表" + "sidebarTitle": "创建分派策略" } }, "responses": { @@ -36028,7 +38634,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalEventListResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -36037,55 +38643,8 @@ "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 - } - } + "rule_id": "69db2f72a0fe7db6448b1506", + "rule_name": "On-call escalation" } } } @@ -36112,31 +38671,48 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalEventListRequest" + "$ref": "#/components/schemas/CreateEscalationRuleRequest" }, "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "year": 2024, - "month": 5 + "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/upsert": { + "/channel/escalate/rule/delete": { "post": { - "operationId": "calEventUpsert", - "summary": "创建或更新日历事件", - "description": "创建或更新个人日历自有的事件:休息日或工作日覆盖。", + "operationId": "channelEscalateRuleDelete", + "summary": "删除分派策略", + "description": "删除已禁用的分派策略,使其不再出现在协作空间的策略列表中。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 事件覆盖 [`start_at`, `end_at`) 这些日期,格式为 `YYYY-MM-DD`;`end_at` 必须晚于 `start_at`。\n- 不传 `event_id` 时创建新事件;传入的 `event_id` 必须是该日历已有的事件。\n- 写入时会把该日历自己的其他事件从这些日期上移除:完全落在范围内的事件被删除,部分重叠的被截短,跨越整个范围的被拆成两段,因此这些日期以最后一次写入为准。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/calendars/cal-event-upsert", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可删除,其他状态返回 `InvalidParameter`。\n- 策略为软删除:不再出现在列表中,但 `POST /channel/escalate/rule/info` 仍可查到,`status` 为 `deleted`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-delete", "metadata": { - "sidebarTitle": "创建或更新日历事件" + "sidebarTitle": "删除分派策略" } }, "responses": { @@ -36153,7 +38729,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalEventUpsertResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -36161,11 +38737,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", - "summary": "Test Holiday" - } + "data": {} } } } @@ -36191,34 +38763,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/disable": { "post": { - "operationId": "calendarInfo", - "summary": "获取服务日历详情", - "description": "按 ID 返回账户中一个服务日历的详情。", + "operationId": "channelEscalateRuleDisable", + "summary": "禁用分派策略", + "description": "禁用分派策略但不删除。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不存在的 `cal_id` 返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/calendars/calendar-info", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的策略可禁用,其他状态返回 `InvalidParameter`。\n- 禁用后的策略不再接收新故障,已通过它分派的故障也不再收到它的通知和升级。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-disable", "metadata": { - "sidebarTitle": "获取服务日历详情" + "sidebarTitle": "禁用分派策略" } }, "responses": { @@ -36235,7 +38803,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarItem" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -36243,29 +38811,81 @@ }, "example": { "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 - ], - "created_at": 1702455630, - "updated_at": 1775529526, - "creator_id": 2476444212131, - "updated_by": 3790925372131, - "status": "enabled" - } + "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/ChannelRuleIDRequest" + }, + "example": { + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" + } + } + } + } + } + }, + "/channel/escalate/rule/enable": { + "post": { + "operationId": "channelEscalateRuleEnable", + "summary": "启用分派策略", + "description": "启用已禁用的分派策略,使其重新参与新故障的分派。", + "tags": [ + "On-call/协作空间" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-enable", + "metadata": { + "sidebarTitle": "启用分派策略" + } + }, + "responses": { + "200": { + "description": "成功", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EmptyResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } } @@ -36291,29 +38911,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarIDRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg" + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/calendar/list": { + "/channel/escalate/rule/info": { "post": { - "operationId": "calendarList", - "summary": "查询服务日历列表", - "description": "返回当前账户可见的服务日历列表。", + "operationId": "channelEscalateRuleInfo", + "summary": "获取分派策略详情", + "description": "返回协作空间下的单条分派策略,包括环节、时间窗口和过滤条件。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不传 `kind` 时返回个人日历。`region.official.holiday` 返回公共节假日日历,默认按调用方语言区域过滤,`no_locale` 为 `true` 时不过滤;其 `cal_id` 可填入 `extra_cal_ids`。\n- 列表不分页,`total` 等于返回的条目数。", - "href": "/zh/api-reference/on-call/calendars/calendar-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 已删除的策略仍会返回,`status` 为 `deleted`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-info", "metadata": { - "sidebarTitle": "查询服务日历列表" + "sidebarTitle": "获取分派策略详情" } }, "responses": { @@ -36330,7 +38951,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarListResponse" + "$ref": "#/components/schemas/EscalateRuleItem" } } } @@ -36339,49 +38960,37 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "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, + "channel_id": 6193426913131, + "priority": 0, + "aggr_window": 0, + "rule_name": "Default", + "description": "", + "layers": [ { - "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" + "max_times": 1, + "notify_step": 10, + "target": { + "person_ids": [ + 3790925372131 + ], + "by": { + "follow_preference": true + }, + "webhooks": null + }, + "escalate_window": 30, + "force_escalate": false } ], - "total": 8 + "time_filters": [], + "filters": [], + "status": "enabled", + "template_id": "6321aad26c12104586a88916", + "rule_id": "69bd0ce95a238693176c1d66", + "updated_by": 3790925372131, + "created_at": 1773997289, + "updated_at": 1773997289 } } } @@ -36408,29 +39017,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarListRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "kind": "personal" + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34d0" } } } } } }, - "/calendar/update": { + "/channel/escalate/rule/list": { "post": { - "operationId": "calendarUpdate", - "summary": "更新服务日历", - "description": "更新个人服务日历,仅修改传入的字段。", + "operationId": "channelEscalateRuleList", + "summary": "查询分派策略列表", + "description": "按匹配顺序列出协作空间的分派策略。", "tags": [ - "On-call/日历管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **服务日历管理**(`on-call`) |\n\n## 使用说明\n\n- 除 `cal_id` 外至少传一个字段,否则返回 `InvalidParameter`。\n- 传入 `workdays` 或 `extra_cal_ids` 会整体替换原列表(空数组即清空);`team_id: 0` 表示取消团队归属。\n- `cal_name` 在账户内必须唯一。\n- 仅个人日历可修改,且仅限主体账户、管理员、日历创建者或日历所属团队成员操作,其他调用方返回 `AccessDenied`。\n- 成功时响应只包含 `request_id`,不返回 `data` 字段。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/calendars/calendar-update", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- `channel_id` 不存在时返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-list", "metadata": { - "sidebarTitle": "更新服务日历" + "sidebarTitle": "查询分派策略列表" } }, "responses": { @@ -36447,14 +39057,51 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/ListEscalationRulesResponse" } } } ] }, "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + "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 + } + ] + } } } } @@ -36480,38 +39127,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CalendarUpdateRequest" + "$ref": "#/components/schemas/ChannelScopedListRequest" }, "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 } } } } } }, - "/change/list": { + "/channel/escalate/rule/update": { "post": { - "operationId": "change-read-list", - "summary": "查询变更列表", - "description": "在指定时间窗口内查询变更记录,支持过滤、搜索与分页。", + "operationId": "channelEscalateRuleUpdate", + "summary": "更新分派策略", + "description": "整体替换已有分派策略的配置。", "tags": [ - "On-call/变更管理" + "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `start_time` 和 `end_time` 均为必填:`start_time` 必须小于 `end_time`,且时间跨度不超过 31 天。\n- 变更的 `[start_time, last_time]` 区间与查询时间窗有重叠即视为匹配。\n- 将 `include_events` 设为 `true` 可在 `events` 中附带每个变更的原始变更事件。", - "href": "/zh/api-reference/on-call/changes/change-read-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 整体替换:未传的 `description`、`aggr_window`、`time_filters`、`filters` 会被重置为空或 `0`。只有 `priority` 未传时保持原值。\n- 校验规则与创建相同。不会改变策略的 `status`,启停请使用启用、禁用接口。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-update", "metadata": { - "sidebarTitle": "查询变更列表" + "sidebarTitle": "更新分派策略" } }, "responses": { @@ -36528,7 +39166,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListChangeResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -36536,33 +39174,7 @@ }, "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" - } - ] - } + "data": {} } } } @@ -36588,38 +39200,49 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListChangeRequest" + "$ref": "#/components/schemas/UpdateEscalationRuleRequest" }, "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, + "rule_id": "6621b23f4a2c5e0012ab34d0", + "template_id": "6621b23f4a2c5e0012ab34d1", + "rule_name": "Default escalation", + "layers": [ + { + "target": { + "person_ids": [ + 42 + ], + "by": { + "critical": [ + "voice" + ], + "warning": [ + "sms" + ] + } + } + } + ] } } } } } }, - "/channel/create": { + "/channel/info": { "post": { - "operationId": "channelCreate", - "summary": "创建协作空间", - "description": "创建协作空间,可同时创建默认分派策略和协作空间专属集成。", + "operationId": "channelInfo", + "summary": "获取协作空间详情", + "description": "返回单个协作空间的完整配置,以及近 30 天内活跃故障的统计。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- `channel_name` 在账户内必须唯一,重名返回 `InvalidParameter`。\n- `group.method` 为 `p` 需要 Standard 及以上许可证,为 `i` 需要 Pro 许可证。超过当前套餐的协作空间数量上限同样返回 `NoLicense`。\n- 传入 `escalate_rule` 时,会同时创建一条名为 `Default` 的已启用分派策略,只有一个环节,对 `escalate_rule.target` 通知一次。\n- `plugin_ids` 中的每个 ID 会创建一个该类型的协作空间专属集成,集成名称为该类型名称。\n- `is_external_report_enabled` 为 `true` 时,响应中会额外返回 `external_report_token`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-create", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 已删除的协作空间仍会返回,`status` 为 `deleted`。\n- 私有协作空间(`is_private: true`)仅对账户所有者或管理员、创建者、所属团队或管理团队成员可见,其他调用者返回 `AccessDenied`。\n- 此接口不返回 `team_name`、`creator_name`、`is_starred`,需要时请用 `POST /channel/list`。\n- `channel_id` 不存在时返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/channels/channel-info", "metadata": { - "sidebarTitle": "创建协作空间" + "sidebarTitle": "获取协作空间详情" } }, "responses": { @@ -36636,7 +39259,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelCreateResponse" + "$ref": "#/components/schemas/ChannelItem" } } } @@ -36645,8 +39268,10 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "channel_id": 6294542005131, - "channel_name": "Production Alerts" + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled", + "team_id": 10 } } } @@ -36673,43 +39298,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateChannelRequest" + "$ref": "#/components/schemas/ChannelInfoRequest" }, "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_id": 1001 } } } } } }, - "/channel/delete": { + "/channel/infos": { "post": { - "operationId": "channelDelete", - "summary": "删除协作空间", - "description": "删除已禁用的协作空间,并一并删除其下的策略和协作空间专属集成。", + "operationId": "channelInfos", + "summary": "批量获取协作空间", + "description": "一次返回最多 1,000 个协作空间的 ID、名称和状态。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的协作空间可删除,其他状态返回 `InvalidParameter`。\n- 若仍有共享集成的路由规则(任一 case 或默认分支)指向该协作空间,返回 HTTP 400,`error.code` 为 `ReferenceExist`,`data.refs` 列出引用它的集成。请先通过 `POST /route/upsert` 把它从这些路由中移除。\n- 协作空间下的分派、静默、排除、抑制和订阅策略以及专属集成全部删除。协作空间本身为软删除:`POST /channel/info` 仍可查到,`status` 为 `deleted`。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-delete", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不存在的 ID 会被忽略;已删除的协作空间也会返回,`status` 为 `deleted`。\n- 结果按协作空间创建顺序排列,而不是 `channel_ids` 的顺序。\n- 私有协作空间不做可见性过滤,同样返回。", + "href": "/zh/api-reference/on-call/channels/channel-infos", "metadata": { - "sidebarTitle": "删除协作空间" + "sidebarTitle": "批量获取协作空间" } }, "responses": { @@ -36726,7 +39337,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ChannelInfosResponse" } } } @@ -36734,7 +39345,15 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "items": [ + { + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled" + } + ] + } } } } @@ -36760,29 +39379,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelIDRequest" + "$ref": "#/components/schemas/ChannelInfosRequest" }, "example": { - "channel_id": 3521074710131 + "channel_ids": [ + 1001, + 1002 + ] } } } } } }, - "/channel/disable": { + "/channel/inhibit/rule/create": { "post": { - "operationId": "channelDisable", - "summary": "禁用协作空间", - "description": "禁用协作空间;禁用期间新进入的告警事件全部丢弃。", + "operationId": "channelInhibitRuleCreate", + "summary": "创建抑制策略", + "description": "创建抑制策略,在相关的源告警仍处于活跃状态时屏蔽新的告警事件。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的协作空间可禁用,其他状态返回 `InvalidParameter`。\n- 策略与集成均保留。告警处理链路最长约一分钟后才感知到新状态。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-disable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 需要 Standard 及以上许可证,否则返回 `NoLicense`。\n- 当新事件命中 `target_filters`,且同一协作空间内存在一条未恢复、`alert_key` 不同、命中 `source_filters`、在该事件前 10 分钟内开始、并且 `equals` 中每个字段取值都相同的告警时,该事件被抑制。\n- `equals` 或 `source_filters` 为空,或新事件缺少 `equals` 中列出的标签时,该策略永远不会生效。\n- 抑制策略在排除和静默策略之后检查,命中第一条即生效。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-create", "metadata": { - "sidebarTitle": "禁用协作空间" + "sidebarTitle": "创建抑制策略" } }, "responses": { @@ -36799,7 +39421,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -36807,7 +39429,10 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "rule_id": "69db2f69a0fe7db6448b1504", + "rule_name": "Suppress Info when Critical fires" + } } } } @@ -36833,29 +39458,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/enable": { + "/channel/inhibit/rule/delete": { "post": { - "operationId": "channelEnable", - "summary": "启用协作空间", - "description": "启用已禁用的协作空间,使其重新处理新的告警事件。", + "operationId": "channelInhibitRuleDelete", + "summary": "删除抑制策略", + "description": "删除已禁用的抑制策略,使其不再出现在协作空间的策略列表中。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的协作空间可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-enable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可删除,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-delete", "metadata": { - "sidebarTitle": "启用协作空间" + "sidebarTitle": "删除抑制策略" } }, "responses": { @@ -36906,29 +39560,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/disable": { "post": { - "operationId": "channelEscalateRuleCreate", - "summary": "创建分派策略", - "description": "创建分派策略,决定协作空间的故障通知谁、如何通知。", + "operationId": "channelInhibitRuleDisable", + "summary": "禁用抑制策略", + "description": "禁用抑制策略但不删除。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 策略按 `priority` 从小到大匹配,第一条启用且 `time_filters`、`filters` 都命中新故障的策略负责该故障,其后的策略不再匹配。不传 `priority` 时排在现有策略之后。\n- `template_id` 必须是已存在的通知模板,`person_ids` 中的成员必须存在,`team_ids` 中的团队必须有成员,否则返回 `InvalidParameter`。\n- 新建的策略为 `enabled` 状态。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-create", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的策略可禁用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-disable", "metadata": { - "sidebarTitle": "创建分派策略" + "sidebarTitle": "禁用抑制策略" } }, "responses": { @@ -36945,7 +39600,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -36953,10 +39608,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "rule_id": "69db2f72a0fe7db6448b1506", - "rule_name": "On-call escalation" - } + "data": {} } } } @@ -36982,48 +39634,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/enable": { "post": { - "operationId": "channelEscalateRuleDelete", - "summary": "删除分派策略", - "description": "删除已禁用的分派策略,使其不再出现在协作空间的策略列表中。", + "operationId": "channelInhibitRuleEnable", + "summary": "启用抑制策略", + "description": "启用已禁用的抑制策略,使其重新抑制命中的告警事件。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可删除,其他状态返回 `InvalidParameter`。\n- 策略为软删除:不再出现在列表中,但 `POST /channel/escalate/rule/info` 仍可查到,`status` 为 `deleted`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-delete", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 需要 Standard 及以上许可证,否则返回 `NoLicense`。\n- 仅 `disabled` 状态的策略可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-enable", "metadata": { - "sidebarTitle": "删除分派策略" + "sidebarTitle": "启用抑制策略" } }, "responses": { @@ -37085,19 +39719,19 @@ } } }, - "/channel/escalate/rule/disable": { + "/channel/inhibit/rule/list": { "post": { - "operationId": "channelEscalateRuleDisable", - "summary": "禁用分派策略", - "description": "禁用分派策略但不删除。", + "operationId": "channelInhibitRuleList", + "summary": "查询抑制策略列表", + "description": "按创建时间先后列出协作空间的抑制策略。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的策略可禁用,其他状态返回 `InvalidParameter`。\n- 禁用后的策略不再接收新故障,已通过它分派的故障也不再收到它的通知和升级。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-disable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- `channel_id` 不存在时返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-list", "metadata": { - "sidebarTitle": "禁用分派策略" + "sidebarTitle": "查询抑制策略列表" } }, "responses": { @@ -37114,15 +39748,56 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListInhibitRulesResponse" } } - } - ] - }, - "example": { - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + } + ] + }, + "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 + } + ] + } } } } @@ -37148,30 +39823,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/enable": { + "/channel/inhibit/rule/update": { "post": { - "operationId": "channelEscalateRuleEnable", - "summary": "启用分派策略", - "description": "启用已禁用的分派策略,使其重新参与新故障的分派。", + "operationId": "channelInhibitRuleUpdate", + "summary": "更新抑制策略", + "description": "整体替换已有抑制策略的配置。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-enable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 整体替换:未传的 `source_filters`、`target_filters` 会被清空,未传 `is_directly_discard` 视为 `false`,未传 `description` 会被清空。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-update", "metadata": { - "sidebarTitle": "启用分派策略" + "sidebarTitle": "更新抑制策略" } }, "responses": { @@ -37222,30 +39896,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/info": { + "/channel/list": { "post": { - "operationId": "channelEscalateRuleInfo", - "summary": "获取分派策略详情", - "description": "返回协作空间下的单条分派策略,包括环节、时间窗口和过滤条件。", + "operationId": "channelList", + "summary": "查询协作空间列表", + "description": "分页查询调用者可见的协作空间,支持过滤和排序。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 已删除的策略仍会返回,`status` 为 `deleted`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-info", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不加过滤条件时返回账户内全部协作空间,但不包含调用者无权访问的私有协作空间。已删除的协作空间不会返回。\n- `is_my_team` 与 `is_my_starred` 同时为 `true` 时返回 `InvalidParameter`。`is_my_managed` 优先于这两者。使用 `is_my_managed` 或 `is_my_team` 时忽略 `team_ids`。\n- `is_brief: true` 时每项只含 `channel_id`、`channel_name`、`description`、`status`、`is_starred`,并一次返回全部结果。\n- 请始终传入 `p`。不传时虽然返回第一页,但只要有结果 `has_next_page` 就恒为 `true`。", + "href": "/zh/api-reference/on-call/channels/channel-list", "metadata": { - "sidebarTitle": "获取分派策略详情" + "sidebarTitle": "查询协作空间列表" } }, "responses": { @@ -37262,7 +39940,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EscalateRuleItem" + "$ref": "#/components/schemas/ListChannelsResponse" } } } @@ -37271,37 +39949,15 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "account_id": 2451002751131, - "channel_id": 6193426913131, - "priority": 0, - "aggr_window": 0, - "rule_name": "Default", - "description": "", - "layers": [ + "total": 42, + "has_next_page": true, + "items": [ { - "max_times": 1, - "notify_step": 10, - "target": { - "person_ids": [ - 3790925372131 - ], - "by": { - "follow_preference": true - }, - "webhooks": null - }, - "escalate_window": 30, - "force_escalate": false + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled" } - ], - "time_filters": [], - "filters": [], - "status": "enabled", - "template_id": "6321aad26c12104586a88916", - "rule_id": "69bd0ce95a238693176c1d66", - "updated_by": 3790925372131, - "created_at": 1773997289, - "updated_at": 1773997289 + ] } } } @@ -37328,30 +39984,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/ListChannelsRequest" }, "example": { - "channel_id": 1001, - "rule_id": "6621b23f4a2c5e0012ab34d0" + "p": 1, + "limit": 20, + "orderby": "created_at", + "asc": false } } } } } }, - "/channel/escalate/rule/list": { + "/channel/silence/rule/create": { "post": { - "operationId": "channelEscalateRuleList", - "summary": "查询分派策略列表", - "description": "按匹配顺序列出协作空间的分派策略。", + "operationId": "channelSilenceRuleCreate", + "summary": "创建静默策略", + "description": "创建静默策略,在时间窗口内屏蔽或丢弃命中的告警事件。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- `channel_id` 不存在时返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- `time_filter`(一次性窗口)与 `time_filters`(周期窗口)必须且只能设置其一,且 `filters` 至少包含一个条件,否则返回 `InvalidParameter`。\n- 每个进入的事件依次经过排除策略、静默策略、抑制策略。命中第一条启用、时间窗口覆盖当前时刻且 `filters` 匹配的静默策略即生效。\n- 设置 `from_incident_id` 时,每个故障只能有一条启用的静默策略,再次创建返回 `InvalidParameter`。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-silence-rule-create", "metadata": { - "sidebarTitle": "查询分派策略列表" + "sidebarTitle": "创建静默策略" } }, "responses": { @@ -37368,7 +40026,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListEscalationRulesResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -37377,41 +40035,8 @@ "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 - } - ] + "rule_id": "69db2f66a0fe7db6448b1503", + "rule_name": "Maintenance window silence" } } } @@ -37438,29 +40063,47 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelScopedListRequest" + "$ref": "#/components/schemas/CreateSilenceRuleRequest" }, "example": { - "channel_id": 1001 + "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/update": { + "/channel/silence/rule/delete": { "post": { - "operationId": "channelEscalateRuleUpdate", - "summary": "更新分派策略", - "description": "整体替换已有分派策略的配置。", + "operationId": "channelSilenceRuleDelete", + "summary": "删除静默策略", + "description": "删除已禁用的静默策略,使其不再出现在协作空间的策略列表中。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 整体替换:未传的 `description`、`aggr_window`、`time_filters`、`filters` 会被重置为空或 `0`。只有 `priority` 未传时保持原值。\n- 校验规则与创建相同。不会改变策略的 `status`,启停请使用启用、禁用接口。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-escalate-rule-update", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可删除,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-silence-rule-delete", "metadata": { - "sidebarTitle": "更新分派策略" + "sidebarTitle": "删除静默策略" } }, "responses": { @@ -37511,49 +40154,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/disable": { "post": { - "operationId": "channelInfo", - "summary": "获取协作空间详情", - "description": "返回单个协作空间的完整配置,以及近 30 天内活跃故障的统计。", + "operationId": "channelSilenceRuleDisable", + "summary": "禁用静默策略", + "description": "禁用静默策略但不删除。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 已删除的协作空间仍会返回,`status` 为 `deleted`。\n- 私有协作空间(`is_private: true`)仅对账户所有者或管理员、创建者、所属团队或管理团队成员可见,其他调用者返回 `AccessDenied`。\n- 此接口不返回 `team_name`、`creator_name`、`is_starred`,需要时请用 `POST /channel/list`。\n- `channel_id` 不存在时返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/channels/channel-info", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的策略可禁用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-silence-rule-disable", "metadata": { - "sidebarTitle": "获取协作空间详情" + "sidebarTitle": "禁用静默策略" } }, "responses": { @@ -37570,7 +40194,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelItem" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -37578,12 +40202,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled", - "team_id": 10 - } + "data": {} } } } @@ -37609,29 +40228,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/enable": { "post": { - "operationId": "channelInfos", - "summary": "批量获取协作空间", - "description": "一次返回最多 1,000 个协作空间的 ID、名称和状态。", + "operationId": "channelSilenceRuleEnable", + "summary": "启用静默策略", + "description": "启用已禁用的静默策略,使其重新静默命中的告警事件。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不存在的 ID 会被忽略;已删除的协作空间也会返回,`status` 为 `deleted`。\n- 结果按协作空间创建顺序排列,而不是 `channel_ids` 的顺序。\n- 私有协作空间不做可见性过滤,同样返回。", - "href": "/zh/api-reference/on-call/channels/channel-infos", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-silence-rule-enable", "metadata": { - "sidebarTitle": "批量获取协作空间" + "sidebarTitle": "启用静默策略" } }, "responses": { @@ -37648,7 +40268,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelInfosResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -37656,15 +40276,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "items": [ - { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled" - } - ] - } + "data": {} } } } @@ -37690,32 +40302,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelInfosRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_ids": [ - 1001, - 1002 - ] + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/inhibit/rule/create": { + "/channel/silence/rule/list": { "post": { - "operationId": "channelInhibitRuleCreate", - "summary": "创建抑制策略", - "description": "创建抑制策略,在相关的源告警仍处于活跃状态时屏蔽新的告警事件。", + "operationId": "channelSilenceRuleList", + "summary": "查询静默策略列表", + "description": "列出协作空间的静默策略,以及每条策略当前是否生效。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 需要 Standard 及以上许可证,否则返回 `NoLicense`。\n- 当新事件命中 `target_filters`,且同一协作空间内存在一条未恢复、`alert_key` 不同、命中 `source_filters`、在该事件前 10 分钟内开始、并且 `equals` 中每个字段取值都相同的告警时,该事件被抑制。\n- `equals` 或 `source_filters` 为空,或新事件缺少 `equals` 中列出的标签时,该策略永远不会生效。\n- 抑制策略在排除和静默策略之后检查,命中第一条即生效。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-create", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 查询列表时会顺带永久移除已到自动清理时间的一次性窗口策略(见 `is_auto_delete`),这些策略不再出现。使用周期 `time_filters` 的策略不会因此被移除。\n- `channel_id` 不存在时返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/channels/channel-silence-rule-list", "metadata": { - "sidebarTitle": "创建抑制策略" + "sidebarTitle": "查询静默策略列表" } }, "responses": { @@ -37732,7 +40342,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/ListSilenceRulesResponse" } } } @@ -37741,8 +40351,38 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "rule_id": "69db2f69a0fe7db6448b1504", - "rule_name": "Suppress Info when Critical fires" + "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, + "status": "enabled", + "rule_id": "69b3c426b4a6f5abf1f54873", + "updated_by": 3790925372131, + "created_at": 1773388838, + "updated_at": 1773388838, + "is_effective": false + } + ] } } } @@ -37769,58 +40409,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateInhibitRuleRequest" + "$ref": "#/components/schemas/ChannelScopedListRequest" }, "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": [ - [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Info" - ] - } - ] - ], - "is_directly_discard": false + "channel_id": 1001 } } } } } }, - "/channel/inhibit/rule/delete": { + "/channel/silence/rule/update": { "post": { - "operationId": "channelInhibitRuleDelete", - "summary": "删除抑制策略", - "description": "删除已禁用的抑制策略,使其不再出现在协作空间的策略列表中。", + "operationId": "channelSilenceRuleUpdate", + "summary": "更新静默策略", + "description": "整体替换已有静默策略的配置。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可删除,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-delete", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 时间窗口与 `filters` 的要求同创建接口。在 `time_filter` 与 `time_filters` 之间切换时,另一种会被清空。\n- `description`、`is_directly_discard`、`is_auto_delete` 总会被覆盖,未传即重置为空或 `false`。`from_incident_id` 不可修改。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-silence-rule-update", "metadata": { - "sidebarTitle": "删除抑制策略" + "sidebarTitle": "更新静默策略" } }, "responses": { @@ -37871,30 +40482,46 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/UpdateSilenceRuleRequest" }, "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34cd", + "rule_name": "Mute during maintenance", + "time_filter": { + "start_time": 1710000000, + "end_time": 1710086400 + }, + "filters": [ + [ + { + "key": "labels.service", + "oper": "IN", + "vals": [ + "billing" + ] + } + ] + ] } } } } } }, - "/channel/inhibit/rule/disable": { + "/channel/unsubscribe/rule/create": { "post": { - "operationId": "channelInhibitRuleDisable", - "summary": "禁用抑制策略", - "description": "禁用抑制策略但不删除。", + "operationId": "channelUnsubscribeRuleCreate", + "summary": "创建排除规则", + "description": "创建排除规则,在生成告警和故障之前丢弃命中的告警事件。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的策略可禁用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-disable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 排除规则最先检查,早于静默和抑制策略。命中任一启用的排除规则的事件直接丢弃,不产生告警、故障或通知。\n- 不传 `filters` 或传空列表时,该规则不匹配任何事件。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-unsubscribe-rule-create", "metadata": { - "sidebarTitle": "禁用抑制策略" + "sidebarTitle": "创建排除规则" } }, "responses": { @@ -37911,7 +40538,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } } } @@ -37919,7 +40546,10 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "rule_id": "69db2f6ba0fe7db6448b1505", + "rule_name": "Drop test environment alerts" + } } } } @@ -37945,30 +40575,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/enable": { + "/channel/unsubscribe/rule/delete": { "post": { - "operationId": "channelInhibitRuleEnable", - "summary": "启用抑制策略", - "description": "启用已禁用的抑制策略,使其重新抑制命中的告警事件。", + "operationId": "channelUnsubscribeRuleDelete", + "summary": "删除排除规则", + "description": "删除已禁用的排除规则,使其不再出现在协作空间的策略列表中。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 需要 Standard 及以上许可证,否则返回 `NoLicense`。\n- 仅 `disabled` 状态的策略可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-enable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的规则可删除,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-unsubscribe-rule-delete", "metadata": { - "sidebarTitle": "启用抑制策略" + "sidebarTitle": "删除排除规则" } }, "responses": { @@ -38030,19 +40673,19 @@ } } }, - "/channel/inhibit/rule/list": { + "/channel/unsubscribe/rule/disable": { "post": { - "operationId": "channelInhibitRuleList", - "summary": "查询抑制策略列表", - "description": "按创建时间先后列出协作空间的抑制策略。", + "operationId": "channelUnsubscribeRuleDisable", + "summary": "禁用排除规则", + "description": "禁用排除规则但不删除。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- `channel_id` 不存在时返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的规则可禁用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-unsubscribe-rule-disable", "metadata": { - "sidebarTitle": "查询抑制策略列表" + "sidebarTitle": "禁用排除规则" } }, "responses": { @@ -38059,7 +40702,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListInhibitRulesResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -38067,48 +40710,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 +40736,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/enable": { "post": { - "operationId": "channelInhibitRuleUpdate", - "summary": "更新抑制策略", - "description": "整体替换已有抑制策略的配置。", + "operationId": "channelUnsubscribeRuleEnable", + "summary": "启用排除规则", + "description": "启用已禁用的排除规则,使其重新丢弃命中的告警事件。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 整体替换:未传的 `source_filters`、`target_filters` 会被清空,未传 `is_directly_discard` 视为 `false`,未传 `description` 会被清空。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-inhibit-rule-update", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的规则可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-unsubscribe-rule-enable", "metadata": { - "sidebarTitle": "更新抑制策略" + "sidebarTitle": "启用排除规则" } }, "responses": { @@ -38207,34 +40810,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateInhibitRuleRequest" + "$ref": "#/components/schemas/ChannelRuleIDRequest" }, "example": { - "channel_id": 1001, - "rule_id": "6621b23f4a2c5e0012ab34ce", - "rule_name": "Suppress downstream", - "equals": [ - "labels.cluster" - ] + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" } } } } } }, - "/channel/list": { + "/channel/unsubscribe/rule/list": { "post": { - "operationId": "channelList", - "summary": "查询协作空间列表", - "description": "分页查询调用者可见的协作空间,支持过滤和排序。", + "operationId": "channelUnsubscribeRuleList", + "summary": "查询排除规则列表", + "description": "按创建时间先后列出协作空间的排除规则。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- 不加过滤条件时返回账户内全部协作空间,但不包含调用者无权访问的私有协作空间。已删除的协作空间不会返回。\n- `is_my_team` 与 `is_my_starred` 同时为 `true` 时返回 `InvalidParameter`。`is_my_managed` 优先于这两者。使用 `is_my_managed` 或 `is_my_team` 时忽略 `team_ids`。\n- `is_brief: true` 时每项只含 `channel_id`、`channel_name`、`description`、`status`、`is_starred`,并一次返回全部结果。\n- 请始终传入 `p`。不传时虽然返回第一页,但只要有结果 `has_next_page` 就恒为 `true`。", - "href": "/zh/api-reference/on-call/channels/channel-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 无 —— 持有有效的 `app_key` 即可调用 |\n\n## 使用说明\n\n- `channel_id` 不存在时返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/channels/channel-unsubscribe-rule-list", "metadata": { - "sidebarTitle": "查询协作空间列表" + "sidebarTitle": "查询排除规则列表" } }, "responses": { @@ -38251,7 +40850,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListChannelsResponse" + "$ref": "#/components/schemas/ListDropRulesResponse" } } } @@ -38260,13 +40859,28 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "total": 42, - "has_next_page": true, "items": [ { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled" + "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 } ] } @@ -38295,32 +40909,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ListChannelsRequest" + "$ref": "#/components/schemas/ChannelScopedListRequest" }, "example": { - "p": 1, - "limit": 20, - "orderby": "created_at", - "asc": false + "channel_id": 1001 } } } } } }, - "/channel/silence/rule/create": { + "/channel/unsubscribe/rule/update": { "post": { - "operationId": "channelSilenceRuleCreate", - "summary": "创建静默策略", - "description": "创建静默策略,在时间窗口内屏蔽或丢弃命中的告警事件。", + "operationId": "channelUnsubscribeRuleUpdate", + "summary": "更新排除规则", + "description": "整体替换已有排除规则的名称、描述和匹配条件。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- `time_filter`(一次性窗口)与 `time_filters`(周期窗口)必须且只能设置其一,且 `filters` 至少包含一个条件,否则返回 `InvalidParameter`。\n- 每个进入的事件依次经过排除策略、静默策略、抑制策略。命中第一条启用、时间窗口覆盖当前时刻且 `filters` 匹配的静默策略即生效。\n- 设置 `from_incident_id` 时,每个故障只能有一条启用的静默策略,再次创建返回 `InvalidParameter`。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-silence-rule-create", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 整体替换:未传 `description` 会被清空;未传 `filters` 会清除全部条件,规则不再匹配任何事件。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-unsubscribe-rule-update", "metadata": { - "sidebarTitle": "创建静默策略" + "sidebarTitle": "更新排除规则" } }, "responses": { @@ -38337,7 +40948,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } } } @@ -38345,10 +40956,7 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": { - "rule_id": "69db2f66a0fe7db6448b1503", - "rule_name": "Maintenance window silence" - } + "data": {} } } } @@ -38374,47 +40982,42 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateSilenceRuleRequest" + "$ref": "#/components/schemas/UpdateDropRuleRequest" }, "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 - }, + "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34cf", + "rule_name": "Drop test alerts", "filters": [ [ { - "key": "severity", + "key": "labels.env", "oper": "IN", "vals": [ - "Info" + "test" ] } ] - ], - "is_directly_discard": false + ] } } } } } }, - "/channel/silence/rule/delete": { + "/channel/update": { "post": { - "operationId": "channelSilenceRuleDelete", - "summary": "删除静默策略", - "description": "删除已禁用的静默策略,使其不再出现在协作空间的策略列表中。", + "operationId": "channelUpdate", + "summary": "更新协作空间", + "description": "更新协作空间设置,仅修改请求中出现的字段。", "tags": [ "On-call/协作空间" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可删除,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-silence-rule-delete", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 未传或为 `null` 的字段保持原值。`group`、`flapping`、`event_group` 一旦传入即整体替换原配置。\n- 传 `managing_team_ids: []` 可清空管理团队。\n- `auto_resolve_mode` 只有与 `auto_resolve_timeout` 一起传入时才生效;只传 `auto_resolve_timeout` 时,模式会重置为 `trigger`。\n- 每次把 `is_external_report_enabled` 设为 `true` 都会生成新的 `external_report_token`,旧令牌随即失效;设为 `false` 会清空令牌。\n- `channel_name` 与其他协作空间重名时返回 `InvalidParameter`;`group.method` 为 `p` 或 `i` 但许可证不足时返回 `NoLicense`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", + "href": "/zh/api-reference/on-call/channels/channel-update", "metadata": { - "sidebarTitle": "删除静默策略" + "sidebarTitle": "更新协作空间" } }, "responses": { @@ -38431,7 +41034,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/UpdateChannelResponse" } } } @@ -38439,7 +41042,9 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "external_report_token": "" + } } } } @@ -38465,30 +41070,31 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "$ref": "#/components/schemas/UpdateChannelRequest" }, "example": { "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" + "channel_name": "Production Alerts (v2)", + "description": "Updated description" } } } } } }, - "/channel/silence/rule/disable": { + "/datasource/im/person/try-link": { "post": { - "operationId": "channelSilenceRuleDisable", - "summary": "禁用静默策略", - "description": "禁用静默策略但不删除。", + "operationId": "datasourceImPersonTryLink", + "summary": "尝试关联 IM 人员", + "description": "为指定集成尝试将未绑定成员自动关联到对应的 IM 账号。", "tags": [ - "On-call/协作空间" + "On-call/集成中心" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `enabled` 状态的策略可禁用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-silence-rule-disable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 按邮箱和手机号查找尚未关联到该集成 IM 应用的所有账户成员;仅支持飞书、钉钉和企业微信集成,其他类型返回 `InvalidParameter`。\n- 已禁用的集成返回 `InvalidParameter`。\n- 同一集成已有关联任务在运行时返回 `RequestLocked`;IM 平台拒绝查询(缺少通讯录权限或凭证被拒)时返回 `InvalidParameter`。\n- 没有成员被新关联时,`new_linked_person_ids` 为空数组。", + "href": "/zh/api-reference/on-call/integrations/datasource-im-person-try-link", "metadata": { - "sidebarTitle": "禁用静默策略" + "sidebarTitle": "尝试关联 IM 人员" } }, "responses": { @@ -38505,7 +41111,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/TryLinkPersonResponse" } } } @@ -38513,7 +41119,13 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "new_linked_person_ids": [ + 5348648172131 + ], + "unmatched_count": 2, + "no_contact_count": 1 + } } } } @@ -38539,30 +41151,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/enable": { + "/datasource/im/war-room-enabled/list": { "post": { - "operationId": "channelSilenceRuleEnable", - "summary": "启用静默策略", - "description": "启用已禁用的静默策略,使其重新静默命中的告警事件。", + "operationId": "im-war-room-enabled-list", + "summary": "查看开启作战室功能的集成", + "description": "查询账户下已开启作战室功能的 IM 集成。", "tags": [ - "On-call/协作空间" + "On-call/IM 集成" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 仅 `disabled` 状态的策略可启用,其他状态返回 `InvalidParameter`。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-silence-rule-enable", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) 或 **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 返回设置中 `war_room_enabled` 为 `true` 的飞书、钉钉、企业微信、Slack 和 Microsoft Teams 集成(含已启用和已禁用),不含已删除的集成。\n- `settings` 中的密钥类字段会被掩码为 `******`。", + "href": "/zh/api-reference/on-call/integrations/im-war-room-enabled-list", "metadata": { - "sidebarTitle": "启用静默策略" + "sidebarTitle": "查看开启作战室功能的集成" } }, "responses": { @@ -38579,7 +41190,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListWarRoomEnabledResponse" } } } @@ -38587,7 +41198,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 + } + ] + } } } } @@ -38613,30 +41252,27 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" + "type": "object" }, - "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" - } + "example": {} } } } } }, - "/channel/silence/rule/list": { + "/enrichment/info": { "post": { - "operationId": "channelSilenceRuleList", - "summary": "查询静默策略列表", - "description": "列出协作空间的静默策略,以及每条策略当前是否生效。", + "operationId": "enrichment-read-info", + "summary": "查看富化规则", + "description": "返回指定集成配置的告警富化规则集。", "tags": [ - "On-call/协作空间" + "On-call/标签增强" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **故障查看**(`on-call`) 或 **故障管理**(`on-call`) |\n\n## 使用说明\n\n- 查询列表时会顺带永久移除已到自动清理时间的一次性窗口策略(见 `is_auto_delete`),这些策略不再出现。使用周期 `time_filters` 的策略不会因此被移除。\n- `channel_id` 不存在时返回 `InvalidParameter`。", - "href": "/zh/api-reference/on-call/channels/channel-silence-rule-list", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间查看**(`on-call`) 或 **协作空间管理**(`on-call`) 或 **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- `integration_id` 必须是账户内已存在的集成,否则返回 `InvalidParameter`。\n- 集成没有配置规则集时返回 `data: null`。", + "href": "/zh/api-reference/on-call/alert-enrichment/enrichment-read-info", "metadata": { - "sidebarTitle": "查询静默策略列表" + "sidebarTitle": "查看富化规则" } }, "responses": { @@ -38653,7 +41289,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListSilenceRulesResponse" + "$ref": "#/components/schemas/EnrichmentItem" } } } @@ -38662,38 +41298,23 @@ "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "items": [ + "integration_id": 5001, + "rules": [ { - "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 + "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 } } } @@ -38720,29 +41341,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChannelScopedListRequest" + "$ref": "#/components/schemas/EnrichmentInfoRequest" }, "example": { - "channel_id": 1001 + "integration_id": 5001 } } } } } }, - "/channel/silence/rule/update": { + "/enrichment/list": { "post": { - "operationId": "channelSilenceRuleUpdate", - "summary": "更新静默策略", - "description": "整体替换已有静默策略的配置。", + "operationId": "enrichment-read-list", + "summary": "批量查询富化规则", + "description": "批量返回指定集成 ID 列表的告警富化规则集。", "tags": [ - "On-call/协作空间" + "On-call/标签增强" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 时间窗口与 `filters` 的要求同创建接口。在 `time_filter` 与 `time_filters` 之间切换时,另一种会被清空。\n- `description`、`is_directly_discard`、`is_auto_delete` 总会被覆盖,未传即重置为空或 `false`。`from_incident_id` 不可修改。\n- `channel_id` 或 `rule_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-silence-rule-update", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **集成中心查看**(`on-call`) 或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 每个 ID 都必须是账户内已存在的集成,否则返回 `InvalidParameter`。\n- 没有配置规则集的集成不会出现在 `items` 中。", + "href": "/zh/api-reference/on-call/alert-enrichment/enrichment-read-list", "metadata": { - "sidebarTitle": "更新静默策略" + "sidebarTitle": "批量查询富化规则" } }, "responses": { @@ -38759,7 +41380,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/EnrichmentListResponse" } } } @@ -38767,7 +41388,19 @@ }, "example": { "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "data": {} + "data": { + "items": [ + { + "integration_id": 5001, + "rules": [], + "status": "enabled", + "updated_by": 80011, + "creator_id": 80011, + "created_at": 1710000000, + "updated_at": 1710000000 + } + ] + } } } } @@ -38793,26 +41426,12 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateSilenceRuleRequest" + "$ref": "#/components/schemas/EnrichmentListRequest" }, "example": { - "channel_id": 1001, - "rule_id": "6621b23f4a2c5e0012ab34cd", - "rule_name": "Mute during maintenance", - "time_filter": { - "start_time": 1710000000, - "end_time": 1710086400 - }, - "filters": [ - [ - { - "key": "labels.service", - "oper": "IN", - "vals": [ - "billing" - ] - } - ] + "integration_ids": [ + 5001, + 5002 ] } } @@ -38820,19 +41439,19 @@ } } }, - "/channel/unsubscribe/rule/create": { + "/enrichment/mapping/api/create": { "post": { - "operationId": "channelUnsubscribeRuleCreate", - "summary": "创建排除规则", - "description": "创建排除规则,在生成告警和故障之前丢弃命中的告警事件。", + "operationId": "mapping-api-write-create", + "summary": "创建映射 API", + "description": "登记一个外部 HTTP API,供富化规则调用以查询告警标签。", "tags": [ - "On-call/协作空间" + "On-call/标签增强" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`) |\n\n## 使用说明\n\n- 排除规则最先检查,早于静默和抑制策略。命中任一启用的排除规则的事件直接丢弃,不产生告警、故障或通知。\n- 不传 `filters` 或传空列表时,该规则不匹配任何事件。\n- `channel_id` 不存在时返回 `InvalidParameter`。\n- 调用者还必须拥有该协作空间的编辑权:账户所有者或管理员、协作空间创建者,或其管理团队成员(`managing_team_ids` 为空时为所属团队成员),否则返回 `AccessDenied`。\n- 每次调用都会记录到账户审计日志。", - "href": "/zh/api-reference/on-call/channels/channel-unsubscribe-rule-create", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **300 次/分钟**;**20 次/秒** |\n| 权限要求 | **映射数据管理**(`on-call`) |\n\n## 使用说明\n\n- `mapping_type` 为 `api` 的富化规则会携带配置的 `headers` 发送 `POST `,请求体为 JSON `{\"result_label_keys\": [...], \"event\": {...}}`(告警事件)。API 须返回 HTTP 200 和 `{\"result_labels\": {\"