From 42e34f22ca50f7bd740aacc3ec8f14addec8a22c Mon Sep 17 00:00:00 2001 From: flashduty-bot Date: Thu, 22 Oct 2026 08:36:53 +0000 Subject: [PATCH 1/3] docs(api-reference): add the four event preview endpoints and two field drifts (api-review 2026-10-22) --- api-reference/on-call.openapi.en.json | 2775 ++++++++++++++++++------- api-reference/on-call.openapi.zh.json | 2775 ++++++++++++++++++------- api-reference/openapi.en.json | 1215 +++++++++++ api-reference/openapi.zh.json | 1215 +++++++++++ docs.json | 12 +- en/openapi/api-catalog.mdx | 8 +- zh/openapi/api-catalog.mdx | 8 +- 7 files changed, 6442 insertions(+), 1566 deletions(-) diff --git a/api-reference/on-call.openapi.en.json b/api-reference/on-call.openapi.en.json index 508b0b9c..6d2dbb96 100644 --- a/api-reference/on-call.openapi.en.json +++ b/api-reference/on-call.openapi.en.json @@ -19015,6 +19015,522 @@ } } } + }, + "/alert/email/preview": { + "post": { + "operationId": "alert-read-email-preview", + "summary": "Preview email-to-alert conversion", + "description": "Run unsaved email integration settings over one email, the way ingestion would.", + "tags": [ + "On-call/Integrations" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Nothing is written: no integration, alert or event is created or changed.\n- `integration_id` seeds the preview with the integration's stored address prefix; the address itself is never used, so the preview works on the create page too.\n- `settings` passes the same validator the save endpoint runs, so an unsupported `mode`, rule `type`, `extract_from` or an invalid `extract_pattern` fails with `InvalidParameter` before the email is parsed.\n- When `eml` is set the message is parsed as a mail file, within the SMTP message size limit, and `email` in the response shows what the parser read.\n- `event` is `null` when the settings discard the email, and `email` is `null` when the message cannot be parsed.\n- In `alwaysTrigger` mode every email becomes its own alert: `alert_key` and `key_source` come back empty.", + "href": "/en/api-reference/on-call/integrations/alert-read-email-preview", + "metadata": { + "sidebarTitle": "Preview email-to-alert conversion" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertEmailPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "result": "trigger", + "matched_rule": 0, + "key_source": "checkout 5xx rate above 2%", + "key_fallback": false, + "alert_key": "8f14e45fceea167a5a36dedd4bea2543", + "event": { + "title": "[ALERT] checkout 5xx rate above 2%", + "description": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "event_status": "Critical", + "event_severity": "Critical", + "labels": { + "from": "alerts@acme.example.com", + "subject": "[ALERT] checkout 5xx rate above 2%" + } + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "from": "alerts@acme.example.com", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "body_text": "The checkout service 5xx rate is 3.4% over the last 5 minutes." + } + } + } + } + } + }, + "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/AlertEmailPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "settings": { + "mode": "triggerOrCloseByRule", + "rules": [ + { + "type": "trigger", + "extract_from": "title", + "extract_pattern": "^\\[ALERT\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[ALERT]/" + ] + } + ] + }, + { + "type": "close", + "extract_from": "title", + "extract_pattern": "^\\[OK\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[OK]/" + ] + } + ] + } + ], + "default": "discard" + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "from": "alerts@acme.example.com" + } + } + } + } + } + } + }, + "/alert/pipeline/preview": { + "post": { + "operationId": "alert-read-pipeline-preview", + "summary": "Preview alert pipeline processing", + "description": "Run unsaved alert processing rules over one event, the way ingestion would.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Nothing is saved and no alert or event is created.\n- The integration's saved enrichment rules run first, then your `rules` in order, against the enriched event.\n- A recovery (`Ok`) event closes the alert without running the pipeline: `is_recovery` is `true` and every step comes back `not_executed` with detail `recovery_event`.\n- `dropped` and `inhibited` report which rule stopped the event: `alert_drop` discards it, `alert_inhibit` discards it while a matching source alert is active. Rules after that one are `not_executed`.\n- When no rule matches, `after` is the event as the notification templates render it, so the preview shows what the channel would deliver.", + "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-preview", + "metadata": { + "sidebarTitle": "Preview alert pipeline processing" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelinePreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "is_recovery": false, + "before": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "after": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "dropped": false, + "inhibited": false, + "steps": [ + { + "index": 0, + "kind": "severity_reset", + "result": "not_matched", + "detail": "condition_not_met" + }, + { + "index": 1, + "kind": "alert_drop", + "result": "not_matched", + "detail": "condition_not_met" + } + ] + } + } + } + } + }, + "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/AlertPipelinePreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "severity_reset", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "test" + ] + } + ], + "settings": { + "severity": "Info" + } + }, + { + "kind": "alert_drop", + "if": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/.*noise.*/" + ] + } + ], + "settings": {} + } + ], + "event": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "event_status": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + } + } + } + } + } + } + }, + "/enrichment/preview": { + "post": { + "operationId": "enrichment-read-preview", + "summary": "Preview enrichment rule results", + "description": "Run unsaved enrichment rules over one event, the way ingestion would.", + "tags": [ + "On-call/Alert enrichment" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Nothing is saved and no alert or event is created.\n- `integration_id` must be an integration of the account, and the caller must be allowed to read it.\n- A `mapping` rule with `mapping_type` = `api` calls the account's mapping API with its stored headers, so the request also needs permission to edit the integration; without it the call fails.\n- `before` is the event as it arrived, `after` is the event after the rules; `steps` explains every rule — whether its conditions matched, why it was skipped, and which labels it added, removed or rewrote.\n- A firing event is rendered the way ingestion does after enrichment, so `[TPL]` labels, title and description in `after` are the final ones.\n- `if` keys must come from the alert or change event vocabulary (`title`, `description`, `labels.`, ...); other keys return `InvalidParameter`.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-preview", + "metadata": { + "sidebarTitle": "Preview enrichment rule results" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "before": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + } + }, + "after": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7", + "service_name": "checkout" + } + }, + "steps": [ + { + "index": 0, + "kind": "extraction", + "matched": true, + "skipped_reason": "", + "detail": "checkout", + "added": { + "service_name": "checkout" + }, + "removed": null, + "changed": null, + "mapping_row": null + } + ] + } + } + } + } + }, + "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/EnrichmentPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "extraction", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "prod" + ] + } + ], + "settings": { + "source_field": "labels.host", + "result_label": "service_name", + "pattern": "^(?P[a-z0-9-]+)-\\d+$", + "override": false + } + } + ], + "event": { + "title": "CPU usage 94% on checkout-7", + "description": "CPU usage above 90% for 5 minutes.", + "event_status": "Critical", + "labels": { + "env": "prod", + "host": "checkout-7", + "check": "cpu" + } + } + } + } + } + } + } + }, + "/enrichment/sample/list": { + "post": { + "operationId": "enrichment-sample-read-list", + "summary": "List recent event samples", + "description": "List the raw events an integration received most recently, newest first.", + "tags": [ + "On-call/Alert enrichment" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Samples are the events as they entered enrichment, so they show exactly the labels your rules match on.\n- The integration must exist and the caller must be allowed to read it.\n- Only the last 20 raw events of an integration are kept, for 7 days; the list is for checking rules, not for searching history.\n- A stored sample keeps its description up to 8 KiB (`description_truncated` marks one that was cut); an event larger than 64 KiB is not kept at all.\n- `dropped` marks a sample the integration discarded before it became an alert.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-sample-read-list", + "metadata": { + "sidebarTitle": "List recent event samples" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentSampleListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "received_at": 1792657352, + "event": { + "title": "CPU usage 94% on checkout-7", + "title_rule": "$service::$check", + "description": "CPU usage above 90% for 5 minutes.", + "alert_key": "cpu-usage-high:checkout-7", + "event_status": "Critical", + "event_severity": "Critical", + "event_time": 1792657345, + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + }, + "images": [] + }, + "description_truncated": false + } + ] + } + } + } + } + }, + "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/EnrichmentSampleListRequest" + }, + "example": { + "integration_id": 6113996590131 + } + } + } + } + } } }, "components": { @@ -28519,6 +29035,14 @@ "type": "string", "description": "Display alias for the entry; not used when sending." }, + "disable_at": { + "type": "boolean", + "description": "Turn @-mentions off for this robot: `true` disables them, `false` forces them on. Omitted keeps the legacy behaviour — on for WeCom, and for other robot types only when `user_schema_id` is set." + }, + "user_schema_id": { + "type": "string", + "description": "ID of the user mapping schema (24-character ObjectID hex) the robot resolves @-mentions through. Required by Feishu robots that mention users; stored lowercased." + }, "data_source_id": { "type": "integer", "format": "int64", @@ -35234,1033 +35758,1639 @@ "description": "ID of the post-mortem the work item is bound to." }, "status": { - "type": "string", - "description": "Work item status after the conversion, usually `open` or `in_progress` (conversion keeps the status)." + "type": "string", + "description": "Work item status after the conversion, usually `open` or `in_progress` (conversion keeps the status)." + } + }, + "title": "i_wi_converted" + }, + "FeedDetailWorkItemBound": { + "type": "object", + "description": "Detail payload for `i_wi_bound`.", + "properties": { + "work_item_id": { + "type": "string", + "description": "Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints." + }, + "item_type": { + "type": "string", + "enum": [ + "action", + "follow_up" + ], + "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." + }, + "title": { + "type": "string", + "description": "Work item title." + }, + "post_mortem_id": { + "type": "string", + "description": "ID of the post-mortem the work item is bound to." + } + }, + "title": "i_wi_bound" + }, + "FeedDetailWorkItemDeleted": { + "type": "object", + "description": "Detail payload for `i_wi_deleted`.", + "properties": { + "work_item_id": { + "type": "string", + "description": "Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints." + }, + "item_type": { + "type": "string", + "enum": [ + "action", + "follow_up" + ], + "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." + }, + "title": { + "type": "string", + "description": "Work item title." + }, + "post_mortem_id": { + "type": "string", + "description": "ID of the post-mortem the work item is bound to." + } + }, + "title": "i_wi_deleted" + }, + "FeedDetailAlertMerge": { + "type": "object", + "title": "a_merge", + "description": "Detail payload for `a_merge`: an alert merged into an incident.", + "properties": { + "comment": { + "type": "string", + "description": "Comment recorded with the merge. Omitted when empty." + }, + "target_incident": { + "$ref": "#/components/schemas/IncidentShort", + "description": "Incident the alerts were merged into. Omitted when not recorded." + }, + "source_alerts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertShort" + }, + "description": "Source alerts merged into the target incident. Omitted when empty." + }, + "owner_id": { + "type": "integer", + "format": "int64", + "description": "New owner member ID set on the target incident. Omitted when unchanged." + }, + "title": { + "type": "string", + "description": "New title set on the target incident. Omitted when unchanged." + } + } + }, + "AlertShort": { + "type": "object", + "description": "Brief alert reference.", + "properties": { + "alert_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Alert ID (ObjectID hex string)." + }, + "title": { + "type": "string", + "description": "Alert title, resolved at read time. Omitted when empty." + } + } + }, + "EventGroup": { + "type": "object", + "description": "Alert event merge configuration. When enabled, repeated incoming events of the same alert are merged into the existing alert within the time window instead of creating new alerts.", + "properties": { + "is_enabled": { + "type": "boolean", + "description": "When true, repeated events of the same alert merge into the existing alert; when false, every event creates a separate alert. If you send `event_group`, set this explicitly: an omitted value means `false`. When the whole `event_group` is omitted on create, merging is enabled." + }, + "time_window": { + "type": "integer", + "minimum": 1, + "description": "Merge window in minutes, required when `is_enabled` is true. The range is 1–1440 by default; accounts with the extended merge window enabled can set up to 10080 (7 days). Ignored when merging is disabled." + } + } + }, + "StatusPageInfoResponse": { + "type": "object", + "description": "Status page detail returned by `GET /status-page/info`: the full page configuration plus feature flags.", + "allOf": [ + { + "$ref": "#/components/schemas/StatusPageItem" + }, + { + "type": "object", + "properties": { + "managed_domain_feature_enabled": { + "type": "boolean", + "description": "Whether the managed custom-domain feature is enabled for this page. `true` for public pages, always `false` for internal pages." + } + }, + "required": [ + "managed_domain_feature_enabled" + ] + } + ] + }, + "StatusPagePreDefinedTemplate": { + "type": "object", + "description": "A predefined event template: a reusable draft of an event's title, type, status, and description. In `POST /status-page/template/upsert`, omit `template_id` to create and supply it to update; on update only non-empty fields are applied.", + "properties": { + "template_id": { + "type": "string", + "description": "Template ID. Omit to create a new template; supply to update an existing one." + }, + "title": { + "type": "string", + "description": "Template title." + }, + "type": { + "type": "string", + "enum": [ + "incident", + "maintenance" + ], + "description": "Change type the template applies to: `incident` unplanned incident, `maintenance` planned maintenance. Set on create; ignored on update." + }, + "status": { + "type": "string", + "enum": [ + "investigating", + "identified", + "monitoring", + "resolved", + "scheduled", + "ongoing", + "completed" + ], + "description": "Change status the template maps to. Incidents use `investigating`/`identified`/`monitoring`/`resolved`; maintenances use `scheduled`/`ongoing`/`completed`." + }, + "description": { + "type": "string", + "description": "Template body text (Markdown)." + } + } + }, + "StatusPageMessageTemplate": { + "type": "object", + "description": "A message template: per-status notification texts for one change type. In `POST /status-page/template/upsert`, omit `template_id` to create and supply it to update; on update only non-empty fields are applied.", + "properties": { + "template_id": { + "type": "string", + "description": "Template ID. Omit to create a new template; supply to update an existing one." + }, + "title": { + "type": "string", + "description": "Template title." + }, + "type": { + "type": "string", + "enum": [ + "incident", + "maintenance" + ], + "description": "Change type the template applies to: `incident` unplanned incident, `maintenance` planned maintenance." + }, + "messages": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Notification text (Markdown) per event status. Keys are change statuses valid for the template's `type` (for example `investigating` or `resolved` for incidents); the value is the text used when the event reaches that status." + } + } + }, + "ListStatusPageTemplatesResponse": { + "type": "object", + "description": "Event template list. Item shape depends on the requested `type`: predefined event templates for `pre_defined`, message templates for `message`.", + "required": [ + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/StatusPagePreDefinedTemplate" + }, + { + "$ref": "#/components/schemas/StatusPageMessageTemplate" + } + ] + }, + "description": "Templates of the requested category." + } + } + }, + "FeedDetailAlertUpdate": { + "type": "object", + "title": "a_update", + "description": "Detail payload for `a_update`: severity/status after the update.", + "properties": { + "severity": { + "$ref": "#/components/schemas/FeedSeverity" + }, + "status": { + "$ref": "#/components/schemas/FeedSeverity" } - }, - "title": "i_wi_converted" + } }, - "FeedDetailWorkItemBound": { + "FeedDetailAlertMuteBySilence": { "type": "object", - "description": "Detail payload for `i_wi_bound`.", + "title": "a_m_silence", + "description": "Detail payload for `a_m_silence`: the alert was muted by a silence rule.", "properties": { - "work_item_id": { - "type": "string", - "description": "Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints." - }, - "item_type": { - "type": "string", - "enum": [ - "action", - "follow_up" - ], - "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." - }, - "title": { + "rule_id": { "type": "string", - "description": "Work item title." + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Silence rule ID that muted the alert. Omitted when empty." }, - "post_mortem_id": { + "rule_name": { "type": "string", - "description": "ID of the post-mortem the work item is bound to." + "description": "Silence rule name, resolved at read time. Omitted when empty." } - }, - "title": "i_wi_bound" + } }, - "FeedDetailWorkItemDeleted": { + "FeedDetailAlertMuteByInhibit": { "type": "object", - "description": "Detail payload for `i_wi_deleted`.", + "title": "a_m_inhibit", + "description": "Detail payload for `a_m_inhibit`: the alert was inhibited by an inhibit rule because of a source alert.", "properties": { - "work_item_id": { + "rule_id": { "type": "string", - "description": "Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints." + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Inhibit rule ID that muted the alert. Omitted when empty." }, - "item_type": { + "rule_name": { "type": "string", - "enum": [ - "action", - "follow_up" - ], - "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." + "description": "Inhibit rule name, resolved at read time. Omitted when empty." }, - "title": { + "source_alert_id": { "type": "string", - "description": "Work item title." + "pattern": "^[0-9a-fA-F]{24}$", + "description": "ID of the source alert that triggered the inhibition. Omitted when empty." }, - "post_mortem_id": { + "source_alert_title": { "type": "string", - "description": "ID of the post-mortem the work item is bound to." + "description": "Title of the source alert, resolved at read time. Omitted when empty." } - }, - "title": "i_wi_deleted" + } }, - "FeedDetailAlertMerge": { + "FeedDetailAlertMuteByFlapping": { "type": "object", - "title": "a_merge", - "description": "Detail payload for `a_merge`: an alert merged into an incident.", + "title": "a_m_flapping", + "description": "Detail payload for `a_m_flapping` (historical): the alert was muted by flapping detection.", "properties": { - "comment": { - "type": "string", - "description": "Comment recorded with the merge. Omitted when empty." - }, - "target_incident": { - "$ref": "#/components/schemas/IncidentShort", - "description": "Incident the alerts were merged into. Omitted when not recorded." - }, - "source_alerts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AlertShort" - }, - "description": "Source alerts merged into the target incident. Omitted when empty." + "max_changes": { + "type": "integer", + "description": "State-change count threshold that triggered flapping detection. Omitted when zero." }, - "owner_id": { + "in_secs": { "type": "integer", - "format": "int64", - "description": "New owner member ID set on the target incident. Omitted when unchanged." + "description": "Window in seconds over which the state changes were counted. Omitted when zero." }, - "title": { - "type": "string", - "description": "New title set on the target incident. Omitted when unchanged." + "mute_secs": { + "type": "integer", + "description": "Mute duration in seconds. Omitted when zero." } } }, - "AlertShort": { + "FeedDetailAlertAck": { "type": "object", - "description": "Brief alert reference.", - "properties": { - "alert_id": { - "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "Alert ID (ObjectID hex string)." - }, - "title": { - "type": "string", - "description": "Alert title, resolved at read time. Omitted when empty." - } - } + "title": "a_ack", + "description": "Detail payload for `a_ack` (historical). No fields.", + "properties": {} }, - "EventGroup": { + "FeedDetailAlertUnack": { "type": "object", - "description": "Alert event merge configuration. When enabled, repeated incoming events of the same alert are merged into the existing alert within the time window instead of creating new alerts.", + "title": "a_unack", + "description": "Detail payload for `a_unack` (historical). No fields.", + "properties": {} + }, + "ScheduleByPersonRequest": { + "type": "object", + "description": "Member on-call status request", "properties": { - "is_enabled": { - "type": "boolean", - "description": "When true, repeated events of the same alert merge into the existing alert; when false, every event creates a separate alert. If you send `event_group`, set this explicitly: an omitted value means `false`. When the whole `event_group` is omitted on create, merging is enabled." - }, - "time_window": { + "person_id": { "type": "integer", - "minimum": 1, - "description": "Merge window in minutes, required when `is_enabled` is true. The range is 1–1440 by default; accounts with the extended merge window enabled can set up to 10080 (7 days). Ignored when merging is disabled." + "description": "Member ID whose on-call status is returned.", + "format": "int64" } - } + }, + "required": [ + "person_id" + ] }, - "StatusPageInfoResponse": { + "ScheduleByPersonResponse": { "type": "object", - "description": "Status page detail returned by `GET /status-page/info`: the full page configuration plus feature flags.", - "allOf": [ - { - "$ref": "#/components/schemas/StatusPageItem" + "description": "The member's on-call status: the shift in progress, the next one, and every enabled schedule they participate in.", + "properties": { + "current": { + "oneOf": [ + { + "$ref": "#/components/schemas/MemberOncallInterval" + }, + { + "type": "null" + } + ], + "description": "Shift in progress now; `null` when the member is not on call." }, - { - "type": "object", - "properties": { - "managed_domain_feature_enabled": { - "type": "boolean", - "description": "Whether the managed custom-domain feature is enabled for this page. `true` for public pages, always `false` for internal pages." + "next": { + "oneOf": [ + { + "$ref": "#/components/schemas/MemberOncallInterval" + }, + { + "type": "null" } - }, - "required": [ - "managed_domain_feature_enabled" - ] + ], + "description": "Next upcoming shift (without `end_at`); `null` when none within 45 days." + }, + "schedules": { + "type": "array", + "description": "All enabled schedules the member participates in.", + "items": { + "$ref": "#/components/schemas/MemberScheduleItem" + } } + }, + "required": [ + "schedules" ] }, - "StatusPagePreDefinedTemplate": { + "MemberScheduleItem": { "type": "object", - "description": "A predefined event template: a reusable draft of an event's title, type, status, and description. In `POST /status-page/template/upsert`, omit `template_id` to create and supply it to update; on update only non-empty fields are applied.", + "description": "An enabled schedule the member participates in.", "properties": { - "template_id": { - "type": "string", - "description": "Template ID. Omit to create a new template; supply to update an existing one." + "schedule_id": { + "type": "integer", + "description": "ID of a schedule the member participates in; pass it to `/schedule/info`.", + "format": "int64" }, - "title": { + "schedule_name": { "type": "string", - "description": "Template title." + "description": "Name of that schedule." + } + } + }, + "MemberOncallInterval": { + "type": "object", + "description": "One on-call shift interval of a member.", + "properties": { + "schedule_id": { + "type": "integer", + "description": "Owning schedule ID.", + "format": "int64" }, - "type": { + "schedule_name": { "type": "string", - "enum": [ - "incident", - "maintenance" - ], - "description": "Change type the template applies to: `incident` unplanned incident, `maintenance` planned maintenance. Set on create; ignored on update." + "description": "Owning schedule name." + }, + "start_at": { + "type": "integer", + "description": "Unix timestamp in seconds - when the shift starts.", + "format": "int64" + }, + "end_at": { + "type": "integer", + "description": "Unix timestamp in seconds when the shift ends. Present on `current`; omitted on `next`.", + "format": "int64" + } + } + }, + "IntegrationTypeListRequest": { + "type": "object", + "description": "Filter parameters for listing integration types.", + "properties": { + "p": { + "type": "integer", + "minimum": 1, + "default": 1, + "description": "Page number, 1-based." + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "Page size. Defaults to 20, maximum 100." }, - "status": { + "orderby": { "type": "string", + "description": "Sort field. When omitted, types are returned in console ranking order.", "enum": [ - "investigating", - "identified", - "monitoring", - "resolved", - "scheduled", - "ongoing", - "completed" - ], - "description": "Change status the template maps to. Incidents use `investigating`/`identified`/`monitoring`/`resolved`; maintenances use `scheduled`/`ongoing`/`completed`." + "id", + "created_at", + "updated_at", + "name", + "type" + ] }, - "description": { + "category": { "type": "string", - "description": "Template body text (Markdown)." + "description": "Comma-separated category filter. Values: `event.alert` (alert events), `event.change` (change events), `im` (IM bots), `webhook` (custom webhooks). Unknown values are not rejected and match nothing." + }, + "asc": { + "type": [ + "boolean", + "null" + ], + "default": true, + "description": "Sort ascending when `true` (the default); descending when `false`." } } }, - "StatusPageMessageTemplate": { + "IntegrationTypeItem": { "type": "object", - "description": "A message template: per-status notification texts for one change type. In `POST /status-page/template/upsert`, omit `template_id` to create and supply it to update; on update only non-empty fields are applied.", + "description": "An integration type the account can configure.", + "required": [ + "plugin_type", + "plugin_type_name", + "plugin_type_logo_url", + "category", + "status", + "supports_api_create" + ], "properties": { - "template_id": { + "plugin_type": { "type": "string", - "description": "Template ID. Omit to create a new template; supply to update an existing one." + "description": "Type key to pass as `plugin_type` when creating an integration, for example `standard.alert`, `prometheus.alert`, `zabbix.alert` or `feishu`. The set grows as integrations are added; this endpoint returns the full list.", + "example": "standard.alert" }, - "title": { + "plugin_type_name": { "type": "string", - "description": "Template title." + "description": "Display name of the type.", + "example": "Standard Alert" }, - "type": { + "plugin_type_logo_url": { + "type": "string", + "description": "Logo URL of the type." + }, + "category": { "type": "string", + "description": "Category the type belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks.", "enum": [ - "incident", - "maintenance" - ], - "description": "Change type the template applies to: `incident` unplanned incident, `maintenance` planned maintenance." + "event.alert", + "event.change", + "im", + "webhook" + ] }, - "messages": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Notification text (Markdown) per event status. Keys are change statuses valid for the template's `type` (for example `investigating` or `resolved` for incidents); the value is the text used when the event reaches that status." + "status": { + "type": "string", + "description": "Platform status of the type: `enabled` types can be used; `disabled` types are switched off platform-wide and `POST /integration/create` or `POST /integration/update` returns `InvalidParameter` for them.", + "enum": [ + "enabled", + "disabled" + ] + }, + "supports_api_create": { + "type": "boolean", + "description": "Whether `POST /integration/create` accepts this type." } } }, - "ListStatusPageTemplatesResponse": { + "ListIntegrationTypesResponse": { "type": "object", - "description": "Event template list. Item shape depends on the requested `type`: predefined event templates for `pre_defined`, message templates for `message`.", + "description": "A page of integration types.", "required": [ + "p", + "limit", + "total", "items" ], "properties": { + "p": { + "type": "integer", + "description": "Page number echoed back." + }, + "limit": { + "type": "integer", + "description": "Page size echoed back." + }, + "total": { + "type": "integer", + "format": "int64", + "description": "Total number of matching types." + }, "items": { "type": "array", + "description": "Integration types on the current page.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/StatusPagePreDefinedTemplate" - }, - { - "$ref": "#/components/schemas/StatusPageMessageTemplate" - } - ] - }, - "description": "Templates of the requested category." + "$ref": "#/components/schemas/IntegrationTypeItem" + } } } }, - "FeedDetailAlertUpdate": { + "ListIntegrationsRequest": { "type": "object", - "title": "a_update", - "description": "Detail payload for `a_update`: severity/status after the update.", + "description": "Filter parameters for listing integrations.", "properties": { - "severity": { - "$ref": "#/components/schemas/FeedSeverity" + "p": { + "type": "integer", + "minimum": 1, + "default": 1, + "description": "Page number, 1-based." + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 100, + "description": "Page size. Defaults to 100, maximum 100." + }, + "orderby": { + "type": "string", + "description": "Sort field. Defaults to `created_at`; `plugin_type` is sorted by the underlying plugin.", + "enum": [ + "created_at", + "updated_at", + "name", + "plugin_type", + "status" + ] + }, + "category": { + "type": "string", + "description": "Comma-separated category filter. Values: `event.alert` (alert events), `event.change` (change events), `im` (IM bots), `webhook` (custom webhooks). Unknown values are not rejected and match nothing." + }, + "type": { + "type": "string", + "description": "Deprecated alias of `plugin_type` (comma-separated type keys such as `prometheus.alert`, `zabbix.alert`). Ignored when `plugin_type` is also set." + }, + "plugin_type": { + "type": "string", + "description": "Comma-separated integration type keys, for example `standard.alert,prometheus.alert`; the keys are the `plugin_type` values from `POST /integration/type/list`." }, "status": { - "$ref": "#/components/schemas/FeedSeverity" - } - } - }, - "FeedDetailAlertMuteBySilence": { - "type": "object", - "title": "a_m_silence", - "description": "Detail payload for `a_m_silence`: the alert was muted by a silence rule.", - "properties": { - "rule_id": { "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "Silence rule ID that muted the alert. Omitted when empty." + "description": "Comma-separated status filter: `enabled` (accepting events) and/or `disabled` (paused)." }, - "rule_name": { + "name": { "type": "string", - "description": "Silence rule name, resolved at read time. Omitted when empty." + "description": "Filter by integration name; matches any name that contains this text." + }, + "ref_ids": { + "type": "array", + "description": "Filter by source reference IDs. Each value must start with `c_` (channel), `a_` (account) or `w_`.", + "items": { + "type": "string" + } + }, + "asc": { + "type": "boolean", + "description": "Sort ascending when true, descending when false." + }, + "is_my_team": { + "type": "boolean", + "description": "Limit the result to integrations owned by your teams." + }, + "team_ids": { + "type": "array", + "description": "Filter by team IDs. With `is_my_team`, the values narrow that set further.", + "items": { + "type": "integer", + "format": "int64" + } } } }, - "FeedDetailAlertMuteByInhibit": { + "IntegrationItem": { "type": "object", - "title": "a_m_inhibit", - "description": "Detail payload for `a_m_inhibit`: the alert was inhibited by an inhibit rule because of a source alert.", + "description": "Public integration list item with full stored configuration. Timestamps are Unix epoch seconds.", + "required": [ + "integration_id", + "team_id", + "plugin_type", + "plugin_type_name", + "category", + "name", + "description", + "status", + "ref_id", + "created_at", + "updated_at", + "last_time", + "editable", + "creator_id", + "updated_by", + "no_editable", + "plugin_id", + "integration_key", + "settings", + "data_source_id", + "account_id", + "exclusive_data_source_id" + ], "properties": { - "rule_id": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints." + }, + "team_id": { + "type": "integer", + "format": "int64", + "description": "ID of the team that owns the integration. `0` when it is not assigned to a team." + }, + "plugin_type": { + "type": "string", + "description": "Integration type, for example `standard.alert` or `zabbix.alert`." + }, + "plugin_type_name": { + "type": "string", + "description": "Display name of the integration type, in the language of the request." + }, + "category": { + "type": "string", + "enum": [ + "event.alert", + "event.change", + "im", + "webhook" + ], + "description": "Category the integration belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks." + }, + "name": { "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "Inhibit rule ID that muted the alert. Omitted when empty." + "description": "Integration name." }, - "rule_name": { + "description": { "type": "string", - "description": "Inhibit rule name, resolved at read time. Omitted when empty." + "description": "Free-form description." }, - "source_alert_id": { + "status": { "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "ID of the source alert that triggered the inhibition. Omitted when empty." + "enum": [ + "enabled", + "disabled" + ], + "description": "Lifecycle status: `enabled` while the integration accepts events, `disabled` when it is paused." }, - "source_alert_title": { + "ref_id": { "type": "string", - "description": "Title of the source alert, resolved at read time. Omitted when empty." - } - } - }, - "FeedDetailAlertMuteByFlapping": { - "type": "object", - "title": "a_m_flapping", - "description": "Detail payload for `a_m_flapping` (historical): the alert was muted by flapping detection.", - "properties": { - "max_changes": { + "description": "Source reference ID, normally `a_` for an account-level integration; legacy `w_` references may also exist. Channel-owned `c_` integrations are excluded." + }, + "created_at": { "type": "integer", - "description": "State-change count threshold that triggered flapping detection. Omitted when zero." + "format": "int64", + "description": "Unix timestamp in seconds when the integration was created." }, - "in_secs": { + "updated_at": { "type": "integer", - "description": "Window in seconds over which the state changes were counted. Omitted when zero." + "format": "int64", + "description": "Unix timestamp in seconds when the integration was last updated." }, - "mute_secs": { + "last_time": { "type": "integer", - "description": "Mute duration in seconds. Omitted when zero." - } - } - }, - "FeedDetailAlertAck": { - "type": "object", - "title": "a_ack", - "description": "Detail payload for `a_ack` (historical). No fields.", - "properties": {} - }, - "FeedDetailAlertUnack": { - "type": "object", - "title": "a_unack", - "description": "Detail payload for `a_unack` (historical). No fields.", - "properties": {} - }, - "ScheduleByPersonRequest": { - "type": "object", - "description": "Member on-call status request", - "properties": { - "person_id": { + "format": "int64", + "description": "Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet." + }, + "last_source_time": { "type": "integer", - "description": "Member ID whose on-call status is returned.", - "format": "int64" - } - }, - "required": [ - "person_id" - ] - }, - "ScheduleByPersonResponse": { - "type": "object", - "description": "The member's on-call status: the shift in progress, the next one, and every enabled schedule they participate in.", - "properties": { - "current": { - "oneOf": [ - { - "$ref": "#/components/schemas/MemberOncallInterval" - }, - { - "type": "null" - } - ], - "description": "Shift in progress now; `null` when the member is not on call." + "format": "int64", + "description": "Unix timestamp in seconds of the most recent event received from the upstream tool, including events dropped before they became alerts. `0` when none has arrived yet." }, - "next": { - "oneOf": [ - { - "$ref": "#/components/schemas/MemberOncallInterval" - }, - { - "type": "null" - } - ], - "description": "Next upcoming shift (without `end_at`); `null` when none within 45 days." + "editable": { + "type": "boolean", + "description": "Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage." }, - "schedules": { - "type": "array", - "description": "All enabled schedules the member participates in.", - "items": { - "$ref": "#/components/schemas/MemberScheduleItem" - } - } - }, - "required": [ - "schedules" - ] - }, - "MemberScheduleItem": { - "type": "object", - "description": "An enabled schedule the member participates in.", - "properties": { - "schedule_id": { + "creator_id": { "type": "integer", - "description": "ID of a schedule the member participates in; pass it to `/schedule/info`.", - "format": "int64" + "format": "int64", + "description": "ID of the member who created the integration." }, - "schedule_name": { - "type": "string", - "description": "Name of that schedule." - } - } - }, - "MemberOncallInterval": { - "type": "object", - "description": "One on-call shift interval of a member.", - "properties": { - "schedule_id": { + "updated_by": { "type": "integer", - "description": "Owning schedule ID.", - "format": "int64" + "format": "int64", + "description": "ID of the member who last updated the integration." }, - "schedule_name": { + "no_editable": { + "type": "boolean", + "description": "Read-only flag. When true, the public APIs do not allow changes to this integration." + }, + "plugin_id": { + "type": "integer", + "format": "int64", + "description": "Internal integration type ID; use `plugin_type`, not this ID, when creating an integration." + }, + "integration_key": { "type": "string", - "description": "Owning schedule name." + "description": "Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`." }, - "start_at": { + "settings": { + "type": "object", + "additionalProperties": true, + "description": "Stored type-specific configuration. Each saved secret (passwords, app secrets, tokens, encryption keys, webhook endpoints, HTTP pull URL and body, headers, custom bodies) is returned as `******`; unset values stay empty." + }, + "data_source_id": { "type": "integer", - "description": "Unix timestamp in seconds - when the shift starts.", - "format": "int64" + "format": "int64", + "description": "Legacy datasource ID, equal to `integration_id`." }, - "end_at": { + "account_id": { "type": "integer", - "description": "Unix timestamp in seconds when the shift ends. Present on `current`; omitted on `next`.", - "format": "int64" + "format": "int64", + "description": "ID of the account that owns the integration." + }, + "exclusive_data_source_id": { + "type": "integer", + "format": "int64", + "description": "Legacy compatibility field; `0` for items returned by this public-integration list." } } }, - "IntegrationTypeListRequest": { + "ListIntegrationsResponse": { "type": "object", - "description": "Filter parameters for listing integration types.", + "description": "A page of integrations.", + "required": [ + "p", + "limit", + "total", + "items" + ], "properties": { "p": { "type": "integer", - "minimum": 1, - "default": 1, - "description": "Page number, 1-based." + "description": "Page number echoed back." }, "limit": { "type": "integer", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "Page size. Defaults to 20, maximum 100." - }, - "orderby": { - "type": "string", - "description": "Sort field. When omitted, types are returned in console ranking order.", - "enum": [ - "id", - "created_at", - "updated_at", - "name", - "type" - ] + "description": "Page size echoed back." }, - "category": { - "type": "string", - "description": "Comma-separated category filter. Values: `event.alert` (alert events), `event.change` (change events), `im` (IM bots), `webhook` (custom webhooks). Unknown values are not rejected and match nothing." + "total": { + "type": "integer", + "format": "int64", + "description": "Total number of matching integrations." }, - "asc": { - "type": [ - "boolean", - "null" - ], - "default": true, - "description": "Sort ascending when `true` (the default); descending when `false`." + "items": { + "type": "array", + "description": "Integrations on the current page.", + "items": { + "$ref": "#/components/schemas/IntegrationItem" + } } } }, - "IntegrationTypeItem": { + "GetIntegrationRequest": { "type": "object", - "description": "An integration type the account can configure.", + "description": "Identifies one integration.", + "required": [ + "integration_id" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", + "example": 6113996590131 + } + } + }, + "IntegrationDetail": { + "type": "object", + "description": "Public integration detail with stored settings and its decrypted key. Timestamps are Unix epoch seconds.", "required": [ + "integration_id", + "team_id", "plugin_type", "plugin_type_name", - "plugin_type_logo_url", "category", + "name", + "description", "status", - "supports_api_create" + "ref_id", + "created_at", + "updated_at", + "last_time", + "editable", + "creator_id", + "updated_by", + "no_editable", + "plugin_id", + "integration_key", + "settings" ], "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints." + }, + "team_id": { + "type": "integer", + "format": "int64", + "description": "ID of the team that owns the integration. `0` when it is not assigned to a team." + }, "plugin_type": { "type": "string", - "description": "Type key to pass as `plugin_type` when creating an integration, for example `standard.alert`, `prometheus.alert`, `zabbix.alert` or `feishu`. The set grows as integrations are added; this endpoint returns the full list.", - "example": "standard.alert" + "description": "Integration type, for example `standard.alert` or `zabbix.alert`." }, "plugin_type_name": { "type": "string", - "description": "Display name of the type.", - "example": "Standard Alert" - }, - "plugin_type_logo_url": { - "type": "string", - "description": "Logo URL of the type." + "description": "Display name of the integration type, in the language of the request." }, "category": { "type": "string", - "description": "Category the type belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks.", "enum": [ "event.alert", "event.change", "im", "webhook" - ] + ], + "description": "Category the integration belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks." + }, + "name": { + "type": "string", + "description": "Integration name." + }, + "description": { + "type": "string", + "description": "Free-form description." }, "status": { "type": "string", - "description": "Platform status of the type: `enabled` types can be used; `disabled` types are switched off platform-wide and `POST /integration/create` or `POST /integration/update` returns `InvalidParameter` for them.", "enum": [ "enabled", "disabled" - ] + ], + "description": "Lifecycle status: `enabled` while the integration accepts events, `disabled` when it is paused." }, - "supports_api_create": { + "ref_id": { + "type": "string", + "description": "Source reference ID, normally `a_` for an account-level integration; legacy `w_` references may also exist. Channel-owned `c_` integrations are excluded." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds when the integration was created." + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds when the integration was last updated." + }, + "last_time": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet." + }, + "last_source_time": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds of the most recent event received from the upstream tool, including events dropped before they became alerts. `0` when none has arrived yet." + }, + "editable": { "type": "boolean", - "description": "Whether `POST /integration/create` accepts this type." - } - } - }, - "ListIntegrationTypesResponse": { - "type": "object", - "description": "A page of integration types.", - "required": [ - "p", - "limit", - "total", - "items" - ], - "properties": { - "p": { + "description": "Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage." + }, + "creator_id": { "type": "integer", - "description": "Page number echoed back." + "format": "int64", + "description": "ID of the member who created the integration." }, - "limit": { + "updated_by": { "type": "integer", - "description": "Page size echoed back." + "format": "int64", + "description": "ID of the member who last updated the integration." }, - "total": { + "no_editable": { + "type": "boolean", + "description": "Read-only flag. When true, the public APIs do not allow changes to this integration." + }, + "plugin_id": { "type": "integer", "format": "int64", - "description": "Total number of matching types." + "description": "Internal integration type ID; use `plugin_type`, not this ID, when creating an integration." }, - "items": { - "type": "array", - "description": "Integration types on the current page.", - "items": { - "$ref": "#/components/schemas/IntegrationTypeItem" + "integration_key": { + "type": "string", + "description": "Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`." + }, + "settings": { + "type": "object", + "additionalProperties": true, + "description": "Stored type-specific configuration. Each saved secret (passwords, app secrets, tokens, encryption keys, webhook endpoints, HTTP pull URL and body, headers, custom bodies) is returned as `******`; unset values stay empty." + }, + "test": { + "type": "object", + "description": "Plugin test result, returned only when a test is performed.", + "x-flashduty-preserve-absence": true, + "required": [ + "success", + "message" + ], + "properties": { + "success": { + "type": "boolean", + "description": "Whether the plugin test succeeded." + }, + "message": { + "type": "string", + "description": "Test failure message; empty on success." + } } } } }, - "ListIntegrationsRequest": { + "CreateIntegrationRequest": { "type": "object", - "description": "Filter parameters for listing integrations.", + "description": "Payload for creating an integration.", + "required": [ + "plugin_type" + ], "properties": { - "p": { - "type": "integer", - "minimum": 1, - "default": 1, - "description": "Page number, 1-based." - }, - "limit": { - "type": "integer", - "minimum": 1, - "maximum": 100, - "default": 100, - "description": "Page size. Defaults to 100, maximum 100." - }, - "orderby": { + "plugin_type": { "type": "string", - "description": "Sort field. Defaults to `created_at`; `plugin_type` is sorted by the underlying plugin.", - "enum": [ - "created_at", - "updated_at", - "name", - "plugin_type", - "status" - ] + "description": "Integration type. Must be one listed by `POST /integration/type/list` with `supports_api_create: true`.", + "example": "standard.alert" }, - "category": { + "name": { "type": "string", - "description": "Comma-separated category filter. Values: `event.alert` (alert events), `event.change` (change events), `im` (IM bots), `webhook` (custom webhooks). Unknown values are not rejected and match nothing." + "minLength": 2, + "maxLength": 49, + "description": "Integration name, 2–49 characters when nonempty; defaults to the integration type name when omitted or empty.", + "example": "Prod metrics alerts" }, - "type": { + "description": { "type": "string", - "description": "Deprecated alias of `plugin_type` (comma-separated type keys such as `prometheus.alert`, `zabbix.alert`). Ignored when `plugin_type` is also set." + "maxLength": 499, + "description": "Free-form description, at most 499 characters." }, - "plugin_type": { - "type": "string", - "description": "Comma-separated integration type keys, for example `standard.alert,prometheus.alert`; the keys are the `plugin_type` values from `POST /integration/type/list`." + "team_id": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Owning team ID; omit or use `0` for no team. A nonzero ID must belong to the current account.", + "example": 1467226103121 }, - "status": { - "type": "string", - "description": "Comma-separated status filter: `enabled` (accepting events) and/or `disabled` (paused)." + "settings": { + "type": "object", + "description": "Type-specific configuration; the accepted keys depend on `plugin_type`.", + "additionalProperties": true }, - "name": { + "integration_key": { "type": "string", - "description": "Filter by integration name; matches any name that contains this text." - }, - "ref_ids": { - "type": "array", - "description": "Filter by source reference IDs. Each value must start with `c_` (channel), `a_` (account) or `w_`.", - "items": { - "type": "string" - } + "minLength": 35, + "maxLength": 35, + "description": "Optional pre-generated key: 35 characters, ending with the account ID modulo 1000 padded to three digits; it must not already be in use. Omit to generate a key." }, - "asc": { + "is_test": { "type": "boolean", - "description": "Sort ascending when true, descending when false." + "description": "Run the plugin test during creation; false when omitted. Inspect the returned `test.success` for the test outcome." + } + } + }, + "CreateIntegrationResponse": { + "type": "object", + "description": "The created integration and its key.", + "required": [ + "integration_id", + "integration_key" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "ID of the new integration.", + "example": 6113996590131 }, - "is_my_team": { - "type": "boolean", - "description": "Limit the result to integrations owned by your teams." + "integration_key": { + "type": "string", + "description": "Integration key for inbound pushes; also readable from `/integration/list` and `/integration/info`.", + "example": "0123456789abcdef0123456789abcdef100" }, - "team_ids": { - "type": "array", - "description": "Filter by team IDs. With `is_my_team`, the values narrow that set further.", - "items": { - "type": "integer", - "format": "int64" + "test": { + "type": "object", + "description": "Plugin test result, returned only when a test is performed.", + "x-flashduty-preserve-absence": true, + "required": [ + "success", + "message" + ], + "properties": { + "success": { + "type": "boolean", + "description": "Whether the plugin test succeeded." + }, + "message": { + "type": "string", + "description": "Test failure message; empty on success." + } } } } }, - "IntegrationItem": { + "UpdateIntegrationRequest": { "type": "object", - "description": "Public integration list item with full stored configuration. Timestamps are Unix epoch seconds.", + "description": "Payload for updating an integration. Only the fields you send are changed.", "required": [ - "integration_id", - "team_id", - "plugin_type", - "plugin_type_name", - "category", - "name", - "description", - "status", - "ref_id", - "created_at", - "updated_at", - "last_time", - "editable", - "creator_id", - "updated_by", - "no_editable", - "plugin_id", - "integration_key", - "settings", - "data_source_id", - "account_id", - "exclusive_data_source_id" + "integration_id" ], "properties": { "integration_id": { "type": "integer", "format": "int64", - "description": "Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints." + "minimum": 1, + "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", + "example": 6113996590131 + }, + "name": { + "type": [ + "string", + "null" + ], + "minLength": 2, + "maxLength": 49, + "description": "New name, 2–49 characters." + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 499, + "description": "New description, at most 499 characters." }, "team_id": { - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "int64", - "description": "ID of the team that owns the integration. `0` when it is not assigned to a team." + "minimum": 0, + "description": "New owning team ID; `0` clears the team assignment." }, - "plugin_type": { - "type": "string", - "description": "Integration type, for example `standard.alert` or `zabbix.alert`." + "settings": { + "type": "object", + "description": "Replacement type-specific configuration. Known sensitive fields omitted or sent as `******` keep their stored value; an explicit empty headers object clears headers. A stored secret cannot be kept while its destination (such as `endpoint`, `url`, or a database host or port) changes.", + "additionalProperties": true }, - "plugin_type_name": { + "is_test": { + "type": "boolean", + "description": "Run the plugin test when submitting `settings`; no test is performed for a metadata-only update." + } + } + }, + "IntegrationLifecycleRequest": { + "type": "object", + "description": "Identifies the integration to act on.", + "required": [ + "integration_id" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", + "example": 6113996590131 + } + } + }, + "RotateIntegrationKeyResponse": { + "type": "object", + "description": "The newly issued integration key.", + "required": [ + "integration_key" + ], + "properties": { + "integration_key": { "type": "string", - "description": "Display name of the integration type, in the language of the request." + "description": "New integration key; the previous key stops working immediately. Also readable from `/integration/list` and `/integration/info`.", + "example": "0123456789abcdef0123456789abcdef100" + } + } + }, + "WorkItemAssignee": { + "description": "One assignee on a work item.", + "properties": { + "id": { + "description": "Member ID. Required when `type` is `person`. Omitted when `type` is `ai_sre`.", + "format": "int64", + "type": "integer" }, - "category": { - "type": "string", + "type": { + "description": "Assignee kind: `person` (a member) or `ai_sre` (the account AI SRE).", "enum": [ - "event.alert", - "event.change", - "im", - "webhook" + "person", + "ai_sre" ], - "description": "Category the integration belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks." + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + "AlertEvent": { + "type": "object", + "description": "One raw alert event, in the shape the ingestion pipeline receives and stores.", + "required": [ + "event_status" + ], + "properties": { + "title": { + "type": "string", + "description": "Event title. Required unless `title_rule` is set; the two are the source of the alert title." }, - "name": { + "title_rule": { "type": "string", - "description": "Integration name." + "description": "Title template such as `$service::$alertname`, built from `labels` when `title` is empty." }, "description": { "type": "string", - "description": "Free-form description." + "description": "Event description, truncated to 2048 characters." }, - "status": { + "alert_key": { + "type": "string", + "description": "Deduplication key that merges events into one alert. Empty is allowed: the preview mints a random key, so nothing is merged." + }, + "event_status": { "type": "string", "enum": [ - "enabled", - "disabled" + "Critical", + "Warning", + "Info", + "Ok" ], - "description": "Lifecycle status: `enabled` while the integration accepts events, `disabled` when it is paused." + "description": "Event status. `Critical`, `Warning` and `Info` are firing events; `Ok` is a recovery." }, - "ref_id": { + "event_severity": { "type": "string", - "description": "Source reference ID, normally `a_` for an account-level integration; legacy `w_` references may also exist. Channel-owned `c_` integrations are excluded." + "enum": [ + "Critical", + "Warning", + "Info" + ], + "description": "Severity carried by a firing event. The preview overwrites it with `event_status` for firing events." }, - "created_at": { + "event_time": { "type": "integer", "format": "int64", - "description": "Unix timestamp in seconds when the integration was created." + "description": "Unix timestamp in seconds. The preview stamps the current time, so the value sent is ignored." }, - "updated_at": { - "type": "integer", - "format": "int64", - "description": "Unix timestamp in seconds when the integration was last updated." + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Event labels. Up to 50 entries; keys are label names, values strings." }, - "last_time": { + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertImage" + }, + "description": "Images attached to the event." + } + } + }, + "EnrichmentPreviewEvent": { + "type": "object", + "description": "The event as the enrichment preview saw it.", + "required": [ + "title", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "Event title after the steps applied so far." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Label set after the steps applied so far." + } + } + }, + "EnrichmentSample": { + "type": "object", + "description": "One raw event an integration received, as it entered enrichment.", + "required": [ + "received_at", + "event", + "description_truncated" + ], + "properties": { + "received_at": { "type": "integer", "format": "int64", - "description": "Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet." + "description": "Unix timestamp in seconds of when the integration received the event." }, - "editable": { + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "The raw event, before any enrichment rule ran." + }, + "description_truncated": { "type": "boolean", - "description": "Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage." + "description": "`true` when the stored description was cut to the sample size limit." }, - "creator_id": { + "dropped": { + "type": "boolean", + "description": "`true` when the integration discarded the event before it became an alert. Omitted when `false`." + } + } + }, + "EnrichStep": { + "type": "object", + "description": "What one enrichment rule did to the event.", + "required": [ + "index", + "kind", + "matched", + "skipped_reason", + "detail", + "added", + "removed", + "changed", + "mapping_row" + ], + "properties": { + "index": { "type": "integer", - "format": "int64", - "description": "ID of the member who created the integration." + "description": "Zero-based position of the rule in `rules`." }, - "updated_by": { - "type": "integer", - "format": "int64", - "description": "ID of the member who last updated the integration." + "kind": { + "type": "string", + "enum": [ + "extraction", + "composition", + "mapping", + "drop" + ], + "description": "Rule type that ran.\n| Value | Meaning |\n|---|---|\n| `extraction` | Extract a value from the alert's `title`, `description` or a `labels.*` key and write it to a label. |\n| `composition` | Render a template against the event and write the result to a label. |\n| `mapping` | Look up labels from a mapping schema or an external mapping API. |\n| `drop` | Remove the listed labels from the alert. |" }, - "no_editable": { + "matched": { "type": "boolean", - "description": "Read-only flag. When true, the public APIs do not allow changes to this integration." - }, - "plugin_id": { - "type": "integer", - "format": "int64", - "description": "Internal integration type ID; use `plugin_type`, not this ID, when creating an integration." + "description": "Whether the rule's `if` conditions all matched. `false` means the rule changed nothing." }, - "integration_key": { + "skipped_reason": { "type": "string", - "description": "Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`." + "description": "Why the rule was skipped: `condition_not_met`, `regex_not_matched`, `source_label_missing`, `mapping_row_not_found`, `result_label_exists` or `error`. Empty when the rule ran." }, - "settings": { - "type": "object", - "additionalProperties": true, - "description": "Stored type-specific configuration. Each saved secret (passwords, app secrets, tokens, encryption keys, webhook endpoints, HTTP pull URL and body, headers, custom bodies) is returned as `******`; unset values stay empty." + "detail": { + "type": "string", + "description": "Rule-specific detail: the matched mapping row, the rendered value, or the error message when `skipped_reason` is `error`." }, - "data_source_id": { - "type": "integer", - "format": "int64", - "description": "Legacy datasource ID, equal to `integration_id`." + "added": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "Labels the rule wrote that were not there before. `null` when it added none." }, - "account_id": { - "type": "integer", - "format": "int64", - "description": "ID of the account that owns the integration." + "removed": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Labels the rule deleted. `null` when it removed none." }, - "exclusive_data_source_id": { - "type": "integer", - "format": "int64", - "description": "Legacy compatibility field; `0` for items returned by this public-integration list." + "changed": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "Labels the rule rewrote, each as a `[old_value, new_value]` pair. `null` when it rewrote none." + }, + "mapping_row": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "The mapping row the rule matched. `null` for a rule that is not a mapping rule or matched no row." } } }, - "ListIntegrationsResponse": { + "AlertPipelinePreviewEvent": { "type": "object", - "description": "A page of integrations.", + "description": "The event as the pipeline preview saw it.", "required": [ - "p", - "limit", - "total", - "items" + "title", + "description", + "severity", + "labels" ], "properties": { - "p": { - "type": "integer", - "description": "Page number echoed back." + "title": { + "type": "string", + "description": "Event title." }, - "limit": { - "type": "integer", - "description": "Page size echoed back." + "description": { + "type": "string", + "description": "Event description." }, - "total": { - "type": "integer", - "format": "int64", - "description": "Total number of matching integrations." + "severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "Severity the event carried at this point." }, - "items": { - "type": "array", - "description": "Integrations on the current page.", - "items": { - "$ref": "#/components/schemas/IntegrationItem" - } + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Label set." } } }, - "GetIntegrationRequest": { + "PipelineStep": { "type": "object", - "description": "Identifies one integration.", + "description": "What one alert processing rule did to the event.", "required": [ - "integration_id" + "index", + "kind", + "result", + "detail" ], "properties": { - "integration_id": { + "index": { "type": "integer", - "format": "int64", - "minimum": 1, - "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", - "example": 6113996590131 + "description": "Zero-based position of the rule in `rules`." + }, + "kind": { + "type": "string", + "enum": [ + "title_reset", + "description_reset", + "severity_reset", + "alert_drop", + "alert_inhibit" + ], + "description": "Rule type that ran.\n| Value | Meaning |\n|---|---|\n| `title_reset` | Rewrote the title from the rule's template. |\n| `description_reset` | Rewrote the description from the rule's template. |\n| `severity_reset` | Reset the severity and status to the rule's `severity`. |\n| `alert_drop` | Discarded the event; no alert is created. |\n| `alert_inhibit` | Discarded the event while a matching source alert is active. |" + }, + "result": { + "type": "string", + "enum": [ + "applied", + "not_matched", + "not_executed" + ], + "description": "Outcome of the rule: `applied` (it changed the event or stopped the pipeline), `not_matched` (its `if` conditions did not all match), or `not_executed` (an earlier rule stopped the pipeline, or the event is a recovery)." + }, + "detail": { + "type": "string", + "description": "`condition_not_met`, `no_active_source_alert`, `inhibit_not_evaluated` or `recovery_event` for those outcomes; otherwise the resulting value or the error message." } } }, - "IntegrationDetail": { + "AlertEmailPreviewSettings": { "type": "object", - "description": "Public integration detail with stored settings and its decrypted key. Timestamps are Unix epoch seconds.", - "required": [ - "integration_id", - "team_id", - "plugin_type", - "plugin_type_name", - "category", - "name", - "description", - "status", - "ref_id", - "created_at", - "updated_at", - "last_time", - "editable", - "creator_id", - "updated_by", - "no_editable", - "plugin_id", - "integration_key", - "settings" - ], + "description": "Email integration settings to preview, in the shape the save endpoint accepts.", "properties": { - "integration_id": { - "type": "integer", - "format": "int64", - "description": "Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints." - }, - "team_id": { - "type": "integer", - "format": "int64", - "description": "ID of the team that owns the integration. `0` when it is not assigned to a team." - }, - "plugin_type": { + "mode": { "type": "string", - "description": "Integration type, for example `standard.alert` or `zabbix.alert`." + "enum": [ + "alwaysTrigger", + "triggerByTitle", + "triggerOrCloseByRule" + ], + "description": "How the integration decides what an email becomes. Omitted defaults to `alwaysTrigger`.\n- `alwaysTrigger`: every email becomes its own alert, keyed randomly.\n- `triggerByTitle`: every email becomes a firing event whose alert key is hashed from the subject.\n- `triggerOrCloseByRule`: `rules` decide whether an email triggers, closes or is discarded, and `default` handles the rest." }, - "plugin_type_name": { - "type": "string", - "description": "Display name of the integration type, in the language of the request." + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertEmailRule" + }, + "description": "Rules tried in order when `mode` is `triggerOrCloseByRule`; each entry must be a non-empty object. At most 50." }, - "category": { + "default": { "type": "string", "enum": [ - "event.alert", - "event.change", - "im", - "webhook" + "trigger", + "discard" ], - "description": "Category the integration belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks." - }, - "name": { - "type": "string", - "description": "Integration name." - }, - "description": { + "description": "What happens to an email that matches no rule when `mode` is `triggerOrCloseByRule`: `trigger` turns it into a firing event, `discard` drops it." + } + } + }, + "AlertEmailRule": { + "type": "object", + "description": "One rule that matches an email and extracts the alert key from it.", + "required": [ + "type", + "extract_from", + "extract_pattern", + "filters" + ], + "properties": { + "type": { "type": "string", - "description": "Free-form description." + "enum": [ + "trigger", + "close" + ], + "description": "`trigger` turns a matching email into a firing event, `close` into a recovery event." }, - "status": { + "extract_from": { "type": "string", "enum": [ - "enabled", - "disabled" + "title", + "description" ], - "description": "Lifecycle status: `enabled` while the integration accepts events, `disabled` when it is paused." + "description": "Which part of the email the alert key is extracted from: `title` or `description`. For `description` the body text is searched first, then the body text with tables, then the description." }, - "ref_id": { + "extract_pattern": { "type": "string", - "description": "Source reference ID, normally `a_` for an account-level integration; legacy `w_` references may also exist. Channel-owned `c_` integrations are excluded." - }, - "created_at": { - "type": "integer", - "format": "int64", - "description": "Unix timestamp in seconds when the integration was created." - }, - "updated_at": { - "type": "integer", - "format": "int64", - "description": "Unix timestamp in seconds when the integration was last updated." - }, - "last_time": { - "type": "integer", - "format": "int64", - "description": "Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet." - }, - "editable": { - "type": "boolean", - "description": "Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage." + "description": "Regular expression the key is extracted with; the captured groups are joined by `,` to form the key source. A pattern that captures nothing falls back to the subject." }, - "creator_id": { - "type": "integer", - "format": "int64", - "description": "ID of the member who created the integration." + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterCondition" + }, + "description": "AND conditions the email must match for the rule to apply. Send `[]` to match every email." + } + } + }, + "AlertEmailPreviewEmail": { + "type": "object", + "description": "The email to run the preview over.", + "properties": { + "subject": { + "type": "string", + "description": "Email subject." }, - "updated_by": { - "type": "integer", - "format": "int64", - "description": "ID of the member who last updated the integration." + "body": { + "type": "string", + "description": "Email body: HTML when it starts with `<`, otherwise plain text." }, - "no_editable": { - "type": "boolean", - "description": "Read-only flag. When true, the public APIs do not allow changes to this integration." + "from": { + "type": "string", + "description": "Sender address." }, - "plugin_id": { - "type": "integer", - "format": "int64", - "description": "Internal integration type ID; use `plugin_type`, not this ID, when creating an integration." + "eml": { + "type": "string", + "description": "A whole email file (`.eml`) as base64. When set it stands in for `subject`, `body` and `from` and is parsed the way the SMTP server parses mail." + } + } + }, + "AlertEmailPreviewEvent": { + "type": "object", + "description": "The alert event the email would have produced.", + "required": [ + "title", + "description", + "event_status", + "event_severity", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "Event title." }, - "integration_key": { + "description": { "type": "string", - "description": "Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`." + "description": "Event description." }, - "settings": { - "type": "object", - "additionalProperties": true, - "description": "Stored type-specific configuration. Each saved secret (passwords, app secrets, tokens, encryption keys, webhook endpoints, HTTP pull URL and body, headers, custom bodies) is returned as `******`; unset values stay empty." + "event_status": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "Status of the event this email produces." }, - "test": { - "type": "object", - "description": "Plugin test result, returned only when a test is performed.", - "x-flashduty-preserve-absence": true, - "required": [ - "success", - "message" + "event_severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" ], - "properties": { - "success": { - "type": "boolean", - "description": "Whether the plugin test succeeded." - }, - "message": { - "type": "string", - "description": "Test failure message; empty on success." - } - } + "description": "Severity of a firing event; empty for a recovery." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Labels taken from the email: the body, sender, recipients and subject are exposed as labels." } } }, - "CreateIntegrationRequest": { + "AlertEmailPreviewParsed": { "type": "object", - "description": "Payload for creating an integration.", + "description": "The email as the conversion read it.", "required": [ - "plugin_type" + "subject", + "from", + "body", + "body_text" ], "properties": { - "plugin_type": { + "subject": { "type": "string", - "description": "Integration type. Must be one listed by `POST /integration/type/list` with `supports_api_create: true`.", - "example": "standard.alert" + "description": "Subject as the parser decoded it." }, - "name": { + "from": { "type": "string", - "minLength": 2, - "maxLength": 49, - "description": "Integration name, 2–49 characters when nonempty; defaults to the integration type name when omitted or empty.", - "example": "Prod metrics alerts" + "description": "Sender address taken from the email." }, - "description": { + "body": { "type": "string", - "maxLength": 499, - "description": "Free-form description, at most 499 characters." - }, - "team_id": { - "type": "integer", - "format": "int64", - "minimum": 0, - "description": "Owning team ID; omit or use `0` for no team. A nonzero ID must belong to the current account.", - "example": 1467226103121 - }, - "settings": { - "type": "object", - "description": "Type-specific configuration; the accepted keys depend on `plugin_type`.", - "additionalProperties": true + "description": "Body the conversion used: the HTML part when there is one, otherwise the text part." }, - "integration_key": { + "body_text": { "type": "string", - "minLength": 35, - "maxLength": 35, - "description": "Optional pre-generated key: 35 characters, ending with the account ID modulo 1000 padded to three digits; it must not already be in use. Omit to generate a key." - }, - "is_test": { - "type": "boolean", - "description": "Run the plugin test during creation; false when omitted. Inspect the returned `test.success` for the test outcome." + "description": "Body as plain text; a key extracted from the description is looked for here first." } } }, - "CreateIntegrationResponse": { + "EnrichmentPreviewRequest": { "type": "object", - "description": "The created integration and its key.", + "description": "Request body of `POST /enrichment/preview`.", "required": [ "integration_id", - "integration_key" + "event" ], "properties": { "integration_id": { "type": "integer", "format": "int64", - "description": "ID of the new integration.", - "example": 6113996590131 + "minimum": 1, + "description": "Integration whose context the preview runs in. The rules you send are not saved." }, - "integration_key": { - "type": "string", - "description": "Integration key for inbound pushes; also readable from `/integration/list` and `/integration/info`.", - "example": "0123456789abcdef0123456789abcdef100" + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/EnrichRule" + }, + "description": "Enrichment rules to try, in order. At most 50. The integration's stored rules are not used." }, - "test": { - "type": "object", - "description": "Plugin test result, returned only when a test is performed.", - "x-flashduty-preserve-absence": true, - "required": [ - "success", - "message" - ], - "properties": { - "success": { - "type": "boolean", - "description": "Whether the plugin test succeeded." - }, - "message": { - "type": "string", - "description": "Test failure message; empty on success." - } - } + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "The event to run the rules over." } } }, - "UpdateIntegrationRequest": { + "EnrichmentPreviewResponse": { "type": "object", - "description": "Payload for updating an integration. Only the fields you send are changed.", + "description": "Result of the enrichment preview.", + "required": [ + "before", + "after", + "steps" + ], + "properties": { + "before": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "The event as it arrived." + }, + "after": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "The event after the rules ran, with the `[TPL]` labels, title and description of a firing event rendered." + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichStep" + }, + "description": "One entry per rule, in the order they ran." + } + } + }, + "EnrichmentSampleListRequest": { + "type": "object", + "description": "Request body of `POST /enrichment/sample/list`.", "required": [ "integration_id" ], @@ -36269,97 +37399,182 @@ "type": "integer", "format": "int64", "minimum": 1, - "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", - "example": 6113996590131 - }, - "name": { - "type": [ - "string", - "null" - ], - "minLength": 2, - "maxLength": 49, - "description": "New name, 2–49 characters." - }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 499, - "description": "New description, at most 499 characters." - }, - "team_id": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0, - "description": "New owning team ID; `0` clears the team assignment." - }, - "settings": { - "type": "object", - "description": "Replacement type-specific configuration. Known sensitive fields omitted or sent as `******` keep their stored value; an explicit empty headers object clears headers. A stored secret cannot be kept while its destination (such as `endpoint`, `url`, or a database host or port) changes.", - "additionalProperties": true - }, - "is_test": { - "type": "boolean", - "description": "Run the plugin test when submitting `settings`; no test is performed for a metadata-only update." + "description": "Integration whose recent raw events to list." } } }, - "IntegrationLifecycleRequest": { + "EnrichmentSampleListResponse": { "type": "object", - "description": "Identifies the integration to act on.", + "description": "Recent raw events of one integration.", "required": [ - "integration_id" + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichmentSample" + }, + "description": "Samples, newest first. Empty when no event has arrived yet." + } + } + }, + "AlertPipelinePreviewRequest": { + "type": "object", + "description": "Request body of `POST /alert/pipeline/preview`.", + "required": [ + "integration_id", + "event" ], "properties": { "integration_id": { "type": "integer", "format": "int64", "minimum": 1, - "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", - "example": 6113996590131 + "description": "Integration whose saved enrichment runs first and whose pipeline context the preview uses." + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertPipeline" + }, + "description": "Alert processing rules to try, in order. At most 50. The integration's stored pipeline is not used." + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "The event to run the rules over." } } }, - "RotateIntegrationKeyResponse": { + "AlertPipelinePreviewResponse": { "type": "object", - "description": "The newly issued integration key.", + "description": "Result of the pipeline preview.", "required": [ - "integration_key" + "is_recovery", + "before", + "after", + "dropped", + "inhibited", + "steps" ], "properties": { - "integration_key": { - "type": "string", - "description": "New integration key; the previous key stops working immediately. Also readable from `/integration/list` and `/integration/info`.", - "example": "0123456789abcdef0123456789abcdef100" + "is_recovery": { + "type": "boolean", + "description": "`true` when the event is a recovery event: ingestion closes the alert without running the pipeline." + }, + "before": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "The event as it arrived." + }, + "after": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "The event as notification templates would render it once the rules ran." + }, + "dropped": { + "type": "boolean", + "description": "`true` when a rule dropped the event, so no alert would be created." + }, + "inhibited": { + "type": "boolean", + "description": "`true` when a rule inhibited the event because a matching source alert is active." + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PipelineStep" + }, + "description": "One entry per rule, in the order they ran." } } }, - "WorkItemAssignee": { - "description": "One assignee on a work item.", + "AlertEmailPreviewRequest": { + "type": "object", + "description": "Request body of `POST /alert/email/preview`.", + "required": [ + "settings", + "email" + ], "properties": { - "id": { - "description": "Member ID. Required when `type` is `person`. Omitted when `type` is `ai_sre`.", + "integration_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Email integration whose saved settings seed the preview. `0` or omitted is what the console sends on the create page, before the integration exists." }, - "type": { - "description": "Assignee kind: `person` (a member) or `ai_sre` (the account AI SRE).", - "enum": [ - "person", - "ai_sre" - ], - "type": "string" + "settings": { + "$ref": "#/components/schemas/AlertEmailPreviewSettings", + "description": "Settings to preview. They are validated the way the save endpoint validates them." + }, + "email": { + "$ref": "#/components/schemas/AlertEmailPreviewEmail", + "description": "The email to convert." } - }, + } + }, + "AlertEmailPreviewResponse": { + "type": "object", + "description": "How the settings treated the email, plus what the conversion read.", "required": [ - "type" + "result", + "matched_rule", + "key_source", + "key_fallback", + "alert_key", + "event", + "email" ], - "type": "object" + "properties": { + "result": { + "type": "string", + "enum": [ + "trigger", + "close", + "discard" + ], + "description": "What the settings make of this email: `trigger` (a firing event), `close` (a recovery event) or `discard` (dropped)." + }, + "matched_rule": { + "type": [ + "integer", + "null" + ], + "description": "Zero-based index of the rule that matched. `null` when no rule matched, and always `null` in `alwaysTrigger` and `triggerByTitle` modes." + }, + "key_source": { + "type": "string", + "description": "What the alert key was hashed from. Empty when every email is its own alert (`alwaysTrigger`) or the email is discarded." + }, + "key_fallback": { + "type": "boolean", + "description": "`true` when the rule's pattern captured nothing and the subject was used as the key source." + }, + "alert_key": { + "type": "string", + "description": "Hash of `key_source`. Empty in `alwaysTrigger` mode, where each email gets a random key." + }, + "event": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewEvent" + }, + { + "type": "null" + } + ], + "description": "The event the email produces. `null` when the email is discarded." + }, + "email": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewParsed" + }, + { + "type": "null" + } + ], + "description": "What the conversion read from the email. `null` when the email could not be parsed." + } + } } } } diff --git a/api-reference/on-call.openapi.zh.json b/api-reference/on-call.openapi.zh.json index 6948e64e..77d2e8c7 100644 --- a/api-reference/on-call.openapi.zh.json +++ b/api-reference/on-call.openapi.zh.json @@ -19015,6 +19015,522 @@ } } } + }, + "/alert/email/preview": { + "post": { + "operationId": "alert-read-email-preview", + "summary": "预览邮件转告警效果", + "description": "用未保存的邮件集成配置,按接入的方式处理一封邮件,返回判定结果与生成的事件。", + "tags": [ + "On-call/集成中心" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 不会写入任何数据:不创建也不修改集成、告警或事件。\n- `integration_id` 只用于带入该集成已存的地址前缀;地址本身不参与处理,因此在新建页面同样可用。\n- `settings` 会走保存接口同一套校验:不支持的 `mode`、规则 `type`、`extract_from` 或非法的 `extract_pattern` 会在解析邮件之前就返回 `InvalidParameter`。\n- 提供 `eml` 时按邮件文件解析,并受 SMTP 邮件大小上限约束;响应中的 `email` 展示解析器实际读到的内容。\n- 配置丢弃该邮件时 `event` 为 `null`;邮件无法解析时 `email` 为 `null`。\n- `alwaysTrigger` 模式下每封邮件都是独立告警,`alert_key` 与 `key_source` 返回空。", + "href": "/zh/api-reference/on-call/integrations/alert-read-email-preview", + "metadata": { + "sidebarTitle": "预览邮件转告警效果" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertEmailPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "result": "trigger", + "matched_rule": 0, + "key_source": "checkout 5xx rate above 2%", + "key_fallback": false, + "alert_key": "8f14e45fceea167a5a36dedd4bea2543", + "event": { + "title": "[ALERT] checkout 5xx rate above 2%", + "description": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "event_status": "Critical", + "event_severity": "Critical", + "labels": { + "from": "alerts@acme.example.com", + "subject": "[ALERT] checkout 5xx rate above 2%" + } + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "from": "alerts@acme.example.com", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "body_text": "The checkout service 5xx rate is 3.4% over the last 5 minutes." + } + } + } + } + } + }, + "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/AlertEmailPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "settings": { + "mode": "triggerOrCloseByRule", + "rules": [ + { + "type": "trigger", + "extract_from": "title", + "extract_pattern": "^\\[ALERT\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[ALERT]/" + ] + } + ] + }, + { + "type": "close", + "extract_from": "title", + "extract_pattern": "^\\[OK\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[OK]/" + ] + } + ] + } + ], + "default": "discard" + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "from": "alerts@acme.example.com" + } + } + } + } + } + } + }, + "/alert/pipeline/preview": { + "post": { + "operationId": "alert-read-pipeline-preview", + "summary": "预览告警处理规则效果", + "description": "用未保存的告警处理规则按接入的方式处理一个事件,返回处理前后的差异。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 不会保存任何内容,也不创建告警或事件。\n- 该集成已存的标签增强规则会先执行,然后按顺序执行你传入的 `rules`,作用在增强后的事件上。\n- 恢复(`Ok`)事件会直接关闭告警、不执行处理规则:`is_recovery` 为 `true`,每一步都是 `not_executed`,`detail` 为 `recovery_event`。\n- `dropped`、`inhibited` 说明是哪类规则中断了事件:`alert_drop` 直接丢弃,`alert_inhibit` 在存在匹配的活跃源告警时丢弃。该规则之后的步骤为 `not_executed`。\n- 没有规则命中时,`after` 是通知模板渲染后的事件,即在协作空间中会看到的内容。", + "href": "/zh/api-reference/on-call/alerts/alert-read-pipeline-preview", + "metadata": { + "sidebarTitle": "预览告警处理规则效果" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelinePreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "is_recovery": false, + "before": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "after": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "dropped": false, + "inhibited": false, + "steps": [ + { + "index": 0, + "kind": "severity_reset", + "result": "not_matched", + "detail": "condition_not_met" + }, + { + "index": 1, + "kind": "alert_drop", + "result": "not_matched", + "detail": "condition_not_met" + } + ] + } + } + } + } + }, + "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/AlertPipelinePreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "severity_reset", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "test" + ] + } + ], + "settings": { + "severity": "Info" + } + }, + { + "kind": "alert_drop", + "if": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/.*noise.*/" + ] + } + ], + "settings": {} + } + ], + "event": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "event_status": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + } + } + } + } + } + } + }, + "/enrichment/preview": { + "post": { + "operationId": "enrichment-read-preview", + "summary": "预览标签增强规则效果", + "description": "用未保存的标签增强规则按接入的方式处理一个事件,返回规则逐步的结果。", + "tags": [ + "On-call/标签增强" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 不会保存任何内容,也不创建告警或事件。\n- `integration_id` 必须是本账户的集成,且调用方有权读取它。\n- `mapping_type` 为 `api` 的 `mapping` 规则会用已存的请求头调用账户的映射 API,因此还需要编辑该集成的权限,否则请求失败。\n- `before` 是事件进入时的样子,`after` 是规则执行后的事件;`steps` 逐条说明规则是否满足条件、为什么被跳过、新增/删除/改写了哪些标签。\n- 触发事件会按接入在增强后的方式渲染,因此 `after` 中的 `[TPL]` 标签、标题和描述就是最终形态。\n- `if` 的条件键必须来自告警或变更事件的键(`title`、`description`、`labels.` 等),其他键返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/alert-enrichment/enrichment-read-preview", + "metadata": { + "sidebarTitle": "预览标签增强规则效果" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "before": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + } + }, + "after": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7", + "service_name": "checkout" + } + }, + "steps": [ + { + "index": 0, + "kind": "extraction", + "matched": true, + "skipped_reason": "", + "detail": "checkout", + "added": { + "service_name": "checkout" + }, + "removed": null, + "changed": null, + "mapping_row": null + } + ] + } + } + } + } + }, + "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/EnrichmentPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "extraction", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "prod" + ] + } + ], + "settings": { + "source_field": "labels.host", + "result_label": "service_name", + "pattern": "^(?P[a-z0-9-]+)-\\d+$", + "override": false + } + } + ], + "event": { + "title": "CPU usage 94% on checkout-7", + "description": "CPU usage above 90% for 5 minutes.", + "event_status": "Critical", + "labels": { + "env": "prod", + "host": "checkout-7", + "check": "cpu" + } + } + } + } + } + } + } + }, + "/enrichment/sample/list": { + "post": { + "operationId": "enrichment-sample-read-list", + "summary": "查询事件样本列表", + "description": "查询某个集成最近收到的原始事件,最新的在前。", + "tags": [ + "On-call/标签增强" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 样本是进入标签增强时的事件,因此能看到规则实际匹配的标签。\n- 集成必须存在,且调用方有权读取它。\n- 每个集成只保留最近 20 条原始事件,保存 7 天;该列表用于核对规则,不用于检索历史。\n- 样本保存最多 8 KiB 的描述(被截断时 `description_truncated` 为 `true`);超过 64 KiB 的事件不会保留。\n- `dropped` 标记集成在事件成为告警之前丢弃的样本。", + "href": "/zh/api-reference/on-call/alert-enrichment/enrichment-sample-read-list", + "metadata": { + "sidebarTitle": "查询事件样本列表" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentSampleListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "received_at": 1792657352, + "event": { + "title": "CPU usage 94% on checkout-7", + "title_rule": "$service::$check", + "description": "CPU usage above 90% for 5 minutes.", + "alert_key": "cpu-usage-high:checkout-7", + "event_status": "Critical", + "event_severity": "Critical", + "event_time": 1792657345, + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + }, + "images": [] + }, + "description_truncated": false + } + ] + } + } + } + } + }, + "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/EnrichmentSampleListRequest" + }, + "example": { + "integration_id": 6113996590131 + } + } + } + } + } } }, "components": { @@ -28519,6 +29035,14 @@ "type": "string", "description": "该条目的显示别名;发送时不使用。" }, + "disable_at": { + "type": "boolean", + "description": "是否关闭该机器人的 @ 提醒:`true` 关闭,`false` 强制开启。不传则沿用原有行为——企业微信默认开启,其他机器人类型仅在设置了 `user_schema_id` 时开启。" + }, + "user_schema_id": { + "type": "string", + "description": "机器人解析 @ 提醒所用的用户映射规则 ID(24 位 ObjectID 十六进制串)。飞书机器人开启 @ 提醒时必须提供;保存时会转为小写。" + }, "data_source_id": { "type": "integer", "format": "int64", @@ -35234,1033 +35758,1639 @@ "description": "跟进事项绑定的故障复盘 ID。" }, "status": { - "type": "string", - "description": "转换后的工作项状态,通常为 `open` 或 `in_progress`(转换不改变状态)。" + "type": "string", + "description": "转换后的工作项状态,通常为 `open` 或 `in_progress`(转换不改变状态)。" + } + }, + "title": "i_wi_converted" + }, + "FeedDetailWorkItemBound": { + "type": "object", + "description": "`i_wi_bound` 的 detail 载荷。", + "properties": { + "work_item_id": { + "type": "string", + "description": "工作项 ID(`wi_` 加随机字符串),可用于 `/incident/work-item/*` 系列接口。" + }, + "item_type": { + "type": "string", + "enum": [ + "action", + "follow_up" + ], + "description": "跟进事项类型。`action`:挂在故障上的处置行动事项;`follow_up`:挂在故障复盘(Post-mortem)上的改进事项。" + }, + "title": { + "type": "string", + "description": "跟进事项标题。" + }, + "post_mortem_id": { + "type": "string", + "description": "跟进事项绑定的故障复盘 ID。" + } + }, + "title": "i_wi_bound" + }, + "FeedDetailWorkItemDeleted": { + "type": "object", + "description": "`i_wi_deleted` 的 detail 载荷。", + "properties": { + "work_item_id": { + "type": "string", + "description": "工作项 ID(`wi_` 加随机字符串),可用于 `/incident/work-item/*` 系列接口。" + }, + "item_type": { + "type": "string", + "enum": [ + "action", + "follow_up" + ], + "description": "跟进事项类型。`action`:挂在故障上的处置行动事项;`follow_up`:挂在故障复盘(Post-mortem)上的改进事项。" + }, + "title": { + "type": "string", + "description": "跟进事项标题。" + }, + "post_mortem_id": { + "type": "string", + "description": "跟进事项绑定的故障复盘 ID。" + } + }, + "title": "i_wi_deleted" + }, + "FeedDetailAlertMerge": { + "type": "object", + "title": "a_merge", + "description": "`a_merge` 的详情数据:告警被合并到故障。", + "properties": { + "comment": { + "type": "string", + "description": "合并时记录的评论。为空时不返回。" + }, + "target_incident": { + "$ref": "#/components/schemas/IncidentShort", + "description": "告警合并到的目标故障。未记录时不返回。" + }, + "source_alerts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertShort" + }, + "description": "被合并进目标故障的源告警。为空时不返回。" + }, + "owner_id": { + "type": "integer", + "format": "int64", + "description": "目标故障被设置的新负责人成员 ID。未变更时不返回。" + }, + "title": { + "type": "string", + "description": "目标故障被设置的新标题。未变更时不返回。" + } + } + }, + "AlertShort": { + "type": "object", + "description": "告警简要引用。", + "properties": { + "alert_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "告警 ID(ObjectID 十六进制字符串)。" + }, + "title": { + "type": "string", + "description": "告警标题,读取时解析填充。为空时不返回。" + } + } + }, + "EventGroup": { + "type": "object", + "description": "告警事件合并配置。启用后,同一告警的重复事件会在时间窗口内并入已有告警,而不是新建告警。", + "properties": { + "is_enabled": { + "type": "boolean", + "description": "为 true 时,同一告警的重复事件并入已有告警;为 false 时每个事件单独生成告警。传入 `event_group` 时请显式设置此字段,不传即为 `false`。创建时完全不传 `event_group` 则默认开启合并。" + }, + "time_window": { + "type": "integer", + "minimum": 1, + "description": "合并窗口(分钟),`is_enabled` 为 true 时必填。默认取值范围 1–1440;开通了扩展合并窗口的账户最大可设 10080(7 天)。关闭合并时忽略。" + } + } + }, + "StatusPageInfoResponse": { + "type": "object", + "description": "`GET /status-page/info` 返回的状态页详情:完整页面配置及特性开关。", + "allOf": [ + { + "$ref": "#/components/schemas/StatusPageItem" + }, + { + "type": "object", + "properties": { + "managed_domain_feature_enabled": { + "type": "boolean", + "description": "该页面是否启用托管自定义域名特性。公开页面为 `true`,内部页面恒为 `false`。" + } + }, + "required": [ + "managed_domain_feature_enabled" + ] + } + ] + }, + "StatusPagePreDefinedTemplate": { + "type": "object", + "description": "预定义事件模板:可复用的事件草稿(标题、类型、状态、描述)。在 `POST /status-page/template/upsert` 中,省略 `template_id` 表示创建,提供则表示更新;更新时仅应用非空字段。", + "properties": { + "template_id": { + "type": "string", + "description": "模板 ID。省略表示创建新模板;提供表示更新已有模板。" + }, + "title": { + "type": "string", + "description": "模板标题。" + }, + "type": { + "type": "string", + "enum": [ + "incident", + "maintenance" + ], + "description": "模板适用的事件类型:`incident` 为非计划故障,`maintenance` 为计划维护。仅创建时设置,更新时忽略。" + }, + "status": { + "type": "string", + "enum": [ + "investigating", + "identified", + "monitoring", + "resolved", + "scheduled", + "ongoing", + "completed" + ], + "description": "模板对应的事件状态。故障事件支持 `investigating`/`identified`/`monitoring`/`resolved`;维护事件支持 `scheduled`/`ongoing`/`completed`。" + }, + "description": { + "type": "string", + "description": "模板正文(Markdown)。" + } + } + }, + "StatusPageMessageTemplate": { + "type": "object", + "description": "消息模板:某一事件类型下、按状态划分的通知文案。在 `POST /status-page/template/upsert` 中,省略 `template_id` 表示创建,提供则表示更新;更新时仅应用非空字段。", + "properties": { + "template_id": { + "type": "string", + "description": "模板 ID。省略表示创建新模板;提供表示更新已有模板。" + }, + "title": { + "type": "string", + "description": "模板标题。" + }, + "type": { + "type": "string", + "enum": [ + "incident", + "maintenance" + ], + "description": "模板适用的事件类型:`incident` 故障,`maintenance` 计划维护。" + }, + "messages": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "按事件状态划分的通知文案(Markdown)。键为与模板 `type` 匹配的事件状态(如故障事件的 `investigating`、`resolved`),值为事件进入该状态时使用的文本。" + } + } + }, + "ListStatusPageTemplatesResponse": { + "type": "object", + "description": "事件模板列表。条目结构取决于请求的 `type`:`pre_defined` 为预定义事件模板,`message` 为消息模板。", + "required": [ + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/StatusPagePreDefinedTemplate" + }, + { + "$ref": "#/components/schemas/StatusPageMessageTemplate" + } + ] + }, + "description": "所请求类别的模板列表。" + } + } + }, + "FeedDetailAlertUpdate": { + "type": "object", + "title": "a_update", + "description": "`a_update` 的详情数据:更新后的严重程度/状态。", + "properties": { + "severity": { + "$ref": "#/components/schemas/FeedSeverity" + }, + "status": { + "$ref": "#/components/schemas/FeedSeverity" } - }, - "title": "i_wi_converted" + } }, - "FeedDetailWorkItemBound": { + "FeedDetailAlertMuteBySilence": { "type": "object", - "description": "`i_wi_bound` 的 detail 载荷。", + "title": "a_m_silence", + "description": "`a_m_silence` 的详情数据:告警被静默规则收敛。", "properties": { - "work_item_id": { - "type": "string", - "description": "工作项 ID(`wi_` 加随机字符串),可用于 `/incident/work-item/*` 系列接口。" - }, - "item_type": { - "type": "string", - "enum": [ - "action", - "follow_up" - ], - "description": "跟进事项类型。`action`:挂在故障上的处置行动事项;`follow_up`:挂在故障复盘(Post-mortem)上的改进事项。" - }, - "title": { + "rule_id": { "type": "string", - "description": "跟进事项标题。" + "pattern": "^[0-9a-fA-F]{24}$", + "description": "收敛该告警的静默规则 ID。为空时不返回。" }, - "post_mortem_id": { + "rule_name": { "type": "string", - "description": "跟进事项绑定的故障复盘 ID。" + "description": "静默规则名称,读取时解析填充。为空时不返回。" } - }, - "title": "i_wi_bound" + } }, - "FeedDetailWorkItemDeleted": { + "FeedDetailAlertMuteByInhibit": { "type": "object", - "description": "`i_wi_deleted` 的 detail 载荷。", + "title": "a_m_inhibit", + "description": "`a_m_inhibit` 的详情数据:告警因源告警被抑制规则收敛。", "properties": { - "work_item_id": { + "rule_id": { "type": "string", - "description": "工作项 ID(`wi_` 加随机字符串),可用于 `/incident/work-item/*` 系列接口。" + "pattern": "^[0-9a-fA-F]{24}$", + "description": "收敛该告警的抑制规则 ID。为空时不返回。" }, - "item_type": { + "rule_name": { "type": "string", - "enum": [ - "action", - "follow_up" - ], - "description": "跟进事项类型。`action`:挂在故障上的处置行动事项;`follow_up`:挂在故障复盘(Post-mortem)上的改进事项。" + "description": "抑制规则名称,读取时解析填充。为空时不返回。" }, - "title": { + "source_alert_id": { "type": "string", - "description": "跟进事项标题。" + "pattern": "^[0-9a-fA-F]{24}$", + "description": "触发抑制的源告警 ID。为空时不返回。" }, - "post_mortem_id": { + "source_alert_title": { "type": "string", - "description": "跟进事项绑定的故障复盘 ID。" + "description": "源告警标题,读取时解析填充。为空时不返回。" } - }, - "title": "i_wi_deleted" + } }, - "FeedDetailAlertMerge": { + "FeedDetailAlertMuteByFlapping": { "type": "object", - "title": "a_merge", - "description": "`a_merge` 的详情数据:告警被合并到故障。", + "title": "a_m_flapping", + "description": "`a_m_flapping` 的详情数据(历史):告警被抖动检测收敛。", "properties": { - "comment": { - "type": "string", - "description": "合并时记录的评论。为空时不返回。" - }, - "target_incident": { - "$ref": "#/components/schemas/IncidentShort", - "description": "告警合并到的目标故障。未记录时不返回。" - }, - "source_alerts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AlertShort" - }, - "description": "被合并进目标故障的源告警。为空时不返回。" + "max_changes": { + "type": "integer", + "description": "触发抖动检测的状态变化次数阈值。为 0 时不返回。" }, - "owner_id": { + "in_secs": { "type": "integer", - "format": "int64", - "description": "目标故障被设置的新负责人成员 ID。未变更时不返回。" + "description": "统计状态变化的时间窗口(秒)。为 0 时不返回。" }, - "title": { - "type": "string", - "description": "目标故障被设置的新标题。未变更时不返回。" + "mute_secs": { + "type": "integer", + "description": "静默时长(秒)。为 0 时不返回。" } } }, - "AlertShort": { + "FeedDetailAlertAck": { "type": "object", - "description": "告警简要引用。", - "properties": { - "alert_id": { - "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "告警 ID(ObjectID 十六进制字符串)。" - }, - "title": { - "type": "string", - "description": "告警标题,读取时解析填充。为空时不返回。" - } - } + "title": "a_ack", + "description": "`a_ack` 的详情数据(历史),无字段。", + "properties": {} }, - "EventGroup": { + "FeedDetailAlertUnack": { "type": "object", - "description": "告警事件合并配置。启用后,同一告警的重复事件会在时间窗口内并入已有告警,而不是新建告警。", + "title": "a_unack", + "description": "`a_unack` 的详情数据(历史),无字段。", + "properties": {} + }, + "ScheduleByPersonRequest": { + "type": "object", + "description": "成员值班状态查询请求", "properties": { - "is_enabled": { - "type": "boolean", - "description": "为 true 时,同一告警的重复事件并入已有告警;为 false 时每个事件单独生成告警。传入 `event_group` 时请显式设置此字段,不传即为 `false`。创建时完全不传 `event_group` 则默认开启合并。" - }, - "time_window": { + "person_id": { "type": "integer", - "minimum": 1, - "description": "合并窗口(分钟),`is_enabled` 为 true 时必填。默认取值范围 1–1440;开通了扩展合并窗口的账户最大可设 10080(7 天)。关闭合并时忽略。" + "description": "要查询值班状态的成员 ID。", + "format": "int64" } - } + }, + "required": [ + "person_id" + ] }, - "StatusPageInfoResponse": { + "ScheduleByPersonResponse": { "type": "object", - "description": "`GET /status-page/info` 返回的状态页详情:完整页面配置及特性开关。", - "allOf": [ - { - "$ref": "#/components/schemas/StatusPageItem" + "description": "成员的值班状态:正在值班的班次、下一次值班,以及其参与的全部启用排班。", + "properties": { + "current": { + "oneOf": [ + { + "$ref": "#/components/schemas/MemberOncallInterval" + }, + { + "type": "null" + } + ], + "description": "正在进行的班次;成员当前不在班时为 `null`。" }, - { - "type": "object", - "properties": { - "managed_domain_feature_enabled": { - "type": "boolean", - "description": "该页面是否启用托管自定义域名特性。公开页面为 `true`,内部页面恒为 `false`。" + "next": { + "oneOf": [ + { + "$ref": "#/components/schemas/MemberOncallInterval" + }, + { + "type": "null" } - }, - "required": [ - "managed_domain_feature_enabled" - ] + ], + "description": "下一次值班(不含 `end_at`);45 天内没有时为 `null`。" + }, + "schedules": { + "type": "array", + "description": "该成员参与的全部启用排班。", + "items": { + "$ref": "#/components/schemas/MemberScheduleItem" + } } + }, + "required": [ + "schedules" ] }, - "StatusPagePreDefinedTemplate": { + "MemberScheduleItem": { "type": "object", - "description": "预定义事件模板:可复用的事件草稿(标题、类型、状态、描述)。在 `POST /status-page/template/upsert` 中,省略 `template_id` 表示创建,提供则表示更新;更新时仅应用非空字段。", + "description": "该成员参与的一个启用中的排班。", "properties": { - "template_id": { - "type": "string", - "description": "模板 ID。省略表示创建新模板;提供表示更新已有模板。" + "schedule_id": { + "type": "integer", + "description": "成员参与的值班表 ID,可传给 `/schedule/info`。", + "format": "int64" }, - "title": { + "schedule_name": { "type": "string", - "description": "模板标题。" + "description": "该值班表的名称。" + } + } + }, + "MemberOncallInterval": { + "type": "object", + "description": "成员的一个值班班次区间。", + "properties": { + "schedule_id": { + "type": "integer", + "description": "所属排班 ID。", + "format": "int64" }, - "type": { + "schedule_name": { "type": "string", - "enum": [ - "incident", - "maintenance" - ], - "description": "模板适用的事件类型:`incident` 为非计划故障,`maintenance` 为计划维护。仅创建时设置,更新时忽略。" + "description": "所属排班名称。" + }, + "start_at": { + "type": "integer", + "description": "Unix 时间戳(秒)—— 班次开始时间。", + "format": "int64" + }, + "end_at": { + "type": "integer", + "description": "班次结束时间(Unix 秒)。`current` 中返回;`next` 中省略。", + "format": "int64" + } + } + }, + "IntegrationTypeListRequest": { + "type": "object", + "description": "查询集成类型列表的过滤参数。", + "properties": { + "p": { + "type": "integer", + "minimum": 1, + "default": 1, + "description": "页码,从 1 开始。" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 20, + "description": "每页条数,默认 20,最大 100。" }, - "status": { + "orderby": { "type": "string", + "description": "排序字段;不传时按控制台排序返回。", "enum": [ - "investigating", - "identified", - "monitoring", - "resolved", - "scheduled", - "ongoing", - "completed" - ], - "description": "模板对应的事件状态。故障事件支持 `investigating`/`identified`/`monitoring`/`resolved`;维护事件支持 `scheduled`/`ongoing`/`completed`。" + "id", + "created_at", + "updated_at", + "name", + "type" + ] }, - "description": { + "category": { "type": "string", - "description": "模板正文(Markdown)。" + "description": "按大类过滤,多个值用逗号分隔。取值:`event.alert`(告警事件)、`event.change`(变更事件)、`im`(IM 机器人)、`webhook`(自定义 Webhook)。未知值不会报错,但匹配不到结果。" + }, + "asc": { + "type": [ + "boolean", + "null" + ], + "default": true, + "description": "`true`(默认)升序,`false` 降序。" } } }, - "StatusPageMessageTemplate": { + "IntegrationTypeItem": { "type": "object", - "description": "消息模板:某一事件类型下、按状态划分的通知文案。在 `POST /status-page/template/upsert` 中,省略 `template_id` 表示创建,提供则表示更新;更新时仅应用非空字段。", + "description": "账户可配置的一种集成类型。", + "required": [ + "plugin_type", + "plugin_type_name", + "plugin_type_logo_url", + "category", + "status", + "supports_api_create" + ], "properties": { - "template_id": { + "plugin_type": { "type": "string", - "description": "模板 ID。省略表示创建新模板;提供表示更新已有模板。" + "description": "创建集成时作为 `plugin_type` 传入的类型标识,如 `standard.alert`、`prometheus.alert`、`zabbix.alert`、`feishu`。类型会随新集成增加,完整列表以本接口返回为准。", + "example": "standard.alert" }, - "title": { + "plugin_type_name": { "type": "string", - "description": "模板标题。" + "description": "类型显示名。", + "example": "Standard Alert" }, - "type": { + "plugin_type_logo_url": { + "type": "string", + "description": "类型 Logo 地址。" + }, + "category": { "type": "string", + "description": "类型所属分类:`event.alert` 告警事件,`event.change` 变更事件,`im` IM 机器人,`webhook` 自定义 Webhook。", "enum": [ - "incident", - "maintenance" - ], - "description": "模板适用的事件类型:`incident` 故障,`maintenance` 计划维护。" + "event.alert", + "event.change", + "im", + "webhook" + ] }, - "messages": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "按事件状态划分的通知文案(Markdown)。键为与模板 `type` 匹配的事件状态(如故障事件的 `investigating`、`resolved`),值为事件进入该状态时使用的文本。" + "status": { + "type": "string", + "description": "该类型的平台状态:`enabled` 可正常使用;`disabled` 表示平台已停用该类型,`POST /integration/create` 与 `POST /integration/update` 会返回 `InvalidParameter`。", + "enum": [ + "enabled", + "disabled" + ] + }, + "supports_api_create": { + "type": "boolean", + "description": "该类型能否通过 `POST /integration/create` 创建。" } } }, - "ListStatusPageTemplatesResponse": { + "ListIntegrationTypesResponse": { "type": "object", - "description": "事件模板列表。条目结构取决于请求的 `type`:`pre_defined` 为预定义事件模板,`message` 为消息模板。", + "description": "集成类型列表的一页。", "required": [ + "p", + "limit", + "total", "items" ], "properties": { + "p": { + "type": "integer", + "description": "当前页码。" + }, + "limit": { + "type": "integer", + "description": "当前每页条数。" + }, + "total": { + "type": "integer", + "format": "int64", + "description": "匹配的类型总数。" + }, "items": { "type": "array", + "description": "当前页的集成类型。", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/StatusPagePreDefinedTemplate" - }, - { - "$ref": "#/components/schemas/StatusPageMessageTemplate" - } - ] - }, - "description": "所请求类别的模板列表。" + "$ref": "#/components/schemas/IntegrationTypeItem" + } } } }, - "FeedDetailAlertUpdate": { + "ListIntegrationsRequest": { "type": "object", - "title": "a_update", - "description": "`a_update` 的详情数据:更新后的严重程度/状态。", + "description": "查询集成列表的过滤参数。", "properties": { - "severity": { - "$ref": "#/components/schemas/FeedSeverity" + "p": { + "type": "integer", + "minimum": 1, + "default": 1, + "description": "页码,从 1 开始。" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 100, + "description": "每页条数,默认 100,最大 100。" + }, + "orderby": { + "type": "string", + "description": "排序字段,默认 `created_at`;`plugin_type` 按底层插件排序。", + "enum": [ + "created_at", + "updated_at", + "name", + "plugin_type", + "status" + ] + }, + "category": { + "type": "string", + "description": "按大类过滤,多个值用逗号分隔。取值:`event.alert`(告警事件)、`event.change`(变更事件)、`im`(IM 机器人)、`webhook`(自定义 Webhook)。未知值不会报错,但匹配不到结果。" + }, + "type": { + "type": "string", + "description": "已弃用,等同于 `plugin_type`(逗号分隔的类型标识,如 `prometheus.alert`、`zabbix.alert`)。同时传入 `plugin_type` 时忽略本字段。" + }, + "plugin_type": { + "type": "string", + "description": "按集成类型过滤,多个值用逗号分隔,如 `standard.alert,prometheus.alert`;取值为 `POST /integration/type/list` 返回的 `plugin_type`。" }, "status": { - "$ref": "#/components/schemas/FeedSeverity" - } - } - }, - "FeedDetailAlertMuteBySilence": { - "type": "object", - "title": "a_m_silence", - "description": "`a_m_silence` 的详情数据:告警被静默规则收敛。", - "properties": { - "rule_id": { "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "收敛该告警的静默规则 ID。为空时不返回。" + "description": "按状态过滤,多个值用逗号分隔:`enabled`(接收事件)、`disabled`(已暂停)。" }, - "rule_name": { + "name": { "type": "string", - "description": "静默规则名称,读取时解析填充。为空时不返回。" + "description": "按集成名称过滤,名称包含该文本即匹配。" + }, + "ref_ids": { + "type": "array", + "description": "按来源引用 ID 过滤;每个值必须以 `c_`(协作空间)、`a_`(账户)或 `w_` 开头。", + "items": { + "type": "string" + } + }, + "asc": { + "type": "boolean", + "description": "`true` 升序,`false` 降序。" + }, + "is_my_team": { + "type": "boolean", + "description": "仅返回你所在团队拥有的集成。" + }, + "team_ids": { + "type": "array", + "description": "按团队 ID 过滤;与 `is_my_team` 同时使用时在其结果内进一步收窄。", + "items": { + "type": "integer", + "format": "int64" + } } } }, - "FeedDetailAlertMuteByInhibit": { + "IntegrationItem": { "type": "object", - "title": "a_m_inhibit", - "description": "`a_m_inhibit` 的详情数据:告警因源告警被抑制规则收敛。", + "description": "公共集成列表项,包含完整存储配置;时间字段为 Unix 时间戳(秒)。", + "required": [ + "integration_id", + "team_id", + "plugin_type", + "plugin_type_name", + "category", + "name", + "description", + "status", + "ref_id", + "created_at", + "updated_at", + "last_time", + "editable", + "creator_id", + "updated_by", + "no_editable", + "plugin_id", + "integration_key", + "settings", + "data_source_id", + "account_id", + "exclusive_data_source_id" + ], "properties": { - "rule_id": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "集成 ID,可作为 `integration_id` 传给其他 `/integration/*` 接口。" + }, + "team_id": { + "type": "integer", + "format": "int64", + "description": "所属团队 ID;未归属团队时为 `0`。" + }, + "plugin_type": { + "type": "string", + "description": "集成类型,例如 `standard.alert`、`zabbix.alert`。" + }, + "plugin_type_name": { + "type": "string", + "description": "集成类型显示名,随请求语言变化。" + }, + "category": { + "type": "string", + "enum": [ + "event.alert", + "event.change", + "im", + "webhook" + ], + "description": "集成所属分类:`event.alert` 告警事件,`event.change` 变更事件,`im` IM 机器人,`webhook` 自定义 Webhook。" + }, + "name": { "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "收敛该告警的抑制规则 ID。为空时不返回。" + "description": "集成名称。" }, - "rule_name": { + "description": { "type": "string", - "description": "抑制规则名称,读取时解析填充。为空时不返回。" + "description": "集成描述。" }, - "source_alert_id": { + "status": { "type": "string", - "pattern": "^[0-9a-fA-F]{24}$", - "description": "触发抑制的源告警 ID。为空时不返回。" + "enum": [ + "enabled", + "disabled" + ], + "description": "状态:`enabled` 正常接收事件,`disabled` 已暂停。" }, - "source_alert_title": { + "ref_id": { "type": "string", - "description": "源告警标题,读取时解析填充。为空时不返回。" - } - } - }, - "FeedDetailAlertMuteByFlapping": { - "type": "object", - "title": "a_m_flapping", - "description": "`a_m_flapping` 的详情数据(历史):告警被抖动检测收敛。", - "properties": { - "max_changes": { + "description": "来源引用 ID,账户级集成通常为 `a_`,旧记录也可能使用 `w_`;本接口不返回 `c_` 开头的专属集成。" + }, + "created_at": { "type": "integer", - "description": "触发抖动检测的状态变化次数阈值。为 0 时不返回。" + "format": "int64", + "description": "创建时间的 Unix 时间戳(秒)。" }, - "in_secs": { + "updated_at": { "type": "integer", - "description": "统计状态变化的时间窗口(秒)。为 0 时不返回。" + "format": "int64", + "description": "最近更新时间的 Unix 时间戳(秒)。" }, - "mute_secs": { + "last_time": { "type": "integer", - "description": "静默时长(秒)。为 0 时不返回。" - } - } - }, - "FeedDetailAlertAck": { - "type": "object", - "title": "a_ack", - "description": "`a_ack` 的详情数据(历史),无字段。", - "properties": {} - }, - "FeedDetailAlertUnack": { - "type": "object", - "title": "a_unack", - "description": "`a_unack` 的详情数据(历史),无字段。", - "properties": {} - }, - "ScheduleByPersonRequest": { - "type": "object", - "description": "成员值班状态查询请求", - "properties": { - "person_id": { + "format": "int64", + "description": "最近收到事件时间的 Unix 时间戳(秒),尚未收到事件时为 `0`。" + }, + "last_source_time": { "type": "integer", - "description": "要查询值班状态的成员 ID。", - "format": "int64" - } - }, - "required": [ - "person_id" - ] - }, - "ScheduleByPersonResponse": { - "type": "object", - "description": "成员的值班状态:正在值班的班次、下一次值班,以及其参与的全部启用排班。", - "properties": { - "current": { - "oneOf": [ - { - "$ref": "#/components/schemas/MemberOncallInterval" - }, - { - "type": "null" - } - ], - "description": "正在进行的班次;成员当前不在班时为 `null`。" + "format": "int64", + "description": "最近一次从上游工具收到事件的时间戳(Unix 秒),包含随后被丢弃、未成为告警的事件;尚未收到过事件时为 `0`。" }, - "next": { - "oneOf": [ - { - "$ref": "#/components/schemas/MemberOncallInterval" - }, - { - "type": "null" - } - ], - "description": "下一次值班(不含 `end_at`);45 天内没有时为 `null`。" + "editable": { + "type": "boolean", + "description": "当前调用者是否通过集成对象权限校验;执行写操作还需集成中心管理权限。" }, - "schedules": { - "type": "array", - "description": "该成员参与的全部启用排班。", - "items": { - "$ref": "#/components/schemas/MemberScheduleItem" - } - } - }, - "required": [ - "schedules" - ] - }, - "MemberScheduleItem": { - "type": "object", - "description": "该成员参与的一个启用中的排班。", - "properties": { - "schedule_id": { + "creator_id": { "type": "integer", - "description": "成员参与的值班表 ID,可传给 `/schedule/info`。", - "format": "int64" + "format": "int64", + "description": "创建集成的成员 ID。" }, - "schedule_name": { - "type": "string", - "description": "该值班表的名称。" - } - } - }, - "MemberOncallInterval": { - "type": "object", - "description": "成员的一个值班班次区间。", - "properties": { - "schedule_id": { + "updated_by": { "type": "integer", - "description": "所属排班 ID。", - "format": "int64" + "format": "int64", + "description": "最近更新集成的成员 ID。" }, - "schedule_name": { + "no_editable": { + "type": "boolean", + "description": "只读标记;为 true 时公开接口不允许修改该集成。" + }, + "plugin_id": { + "type": "integer", + "format": "int64", + "description": "集成类型的内部 ID;创建集成使用 `plugin_type`,不使用此 ID。" + }, + "integration_key": { "type": "string", - "description": "所属排班名称。" + "description": "解密后的集成 Key,用于事件推送;未存储 Key 时为空字符串,与账户 `app_key` 不同。" }, - "start_at": { + "settings": { + "type": "object", + "additionalProperties": true, + "description": "存储的类型专属配置。已保存的密钥类值(密码、App Secret、Token、加密密钥、Webhook 地址、HTTP 拉取的 URL 与 Body、Headers、自定义 Body)返回 `******`,未设置的保持为空。" + }, + "data_source_id": { "type": "integer", - "description": "Unix 时间戳(秒)—— 班次开始时间。", - "format": "int64" + "format": "int64", + "description": "旧 datasource ID,与 `integration_id` 相同。" }, - "end_at": { + "account_id": { "type": "integer", - "description": "班次结束时间(Unix 秒)。`current` 中返回;`next` 中省略。", - "format": "int64" + "format": "int64", + "description": "集成所属账户 ID。" + }, + "exclusive_data_source_id": { + "type": "integer", + "format": "int64", + "description": "旧接口兼容字段;此公共集成列表返回的值为 `0`。" } } }, - "IntegrationTypeListRequest": { + "ListIntegrationsResponse": { "type": "object", - "description": "查询集成类型列表的过滤参数。", + "description": "集成列表的一页。", + "required": [ + "p", + "limit", + "total", + "items" + ], "properties": { "p": { "type": "integer", - "minimum": 1, - "default": 1, - "description": "页码,从 1 开始。" + "description": "当前页码。" }, "limit": { "type": "integer", - "minimum": 1, - "maximum": 100, - "default": 20, - "description": "每页条数,默认 20,最大 100。" - }, - "orderby": { - "type": "string", - "description": "排序字段;不传时按控制台排序返回。", - "enum": [ - "id", - "created_at", - "updated_at", - "name", - "type" - ] + "description": "当前每页条数。" }, - "category": { - "type": "string", - "description": "按大类过滤,多个值用逗号分隔。取值:`event.alert`(告警事件)、`event.change`(变更事件)、`im`(IM 机器人)、`webhook`(自定义 Webhook)。未知值不会报错,但匹配不到结果。" + "total": { + "type": "integer", + "format": "int64", + "description": "匹配的集成总数。" }, - "asc": { - "type": [ - "boolean", - "null" - ], - "default": true, - "description": "`true`(默认)升序,`false` 降序。" + "items": { + "type": "array", + "description": "当前页的集成。", + "items": { + "$ref": "#/components/schemas/IntegrationItem" + } } } }, - "IntegrationTypeItem": { + "GetIntegrationRequest": { "type": "object", - "description": "账户可配置的一种集成类型。", + "description": "指定一个集成。", + "required": [ + "integration_id" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "公共集成 ID,可从 `POST /integration/list` 获取。ID 不存在或属于协作空间专属集成时返回 `ResourceNotFound`。", + "example": 6113996590131 + } + } + }, + "IntegrationDetail": { + "type": "object", + "description": "公共集成详情,包含存储配置与解密 Key;时间字段为 Unix 时间戳(秒)。", "required": [ + "integration_id", + "team_id", "plugin_type", "plugin_type_name", - "plugin_type_logo_url", "category", + "name", + "description", "status", - "supports_api_create" + "ref_id", + "created_at", + "updated_at", + "last_time", + "editable", + "creator_id", + "updated_by", + "no_editable", + "plugin_id", + "integration_key", + "settings" ], "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "集成 ID,可作为 `integration_id` 传给其他 `/integration/*` 接口。" + }, + "team_id": { + "type": "integer", + "format": "int64", + "description": "所属团队 ID;未归属团队时为 `0`。" + }, "plugin_type": { "type": "string", - "description": "创建集成时作为 `plugin_type` 传入的类型标识,如 `standard.alert`、`prometheus.alert`、`zabbix.alert`、`feishu`。类型会随新集成增加,完整列表以本接口返回为准。", - "example": "standard.alert" + "description": "集成类型,例如 `standard.alert`、`zabbix.alert`。" }, "plugin_type_name": { "type": "string", - "description": "类型显示名。", - "example": "Standard Alert" - }, - "plugin_type_logo_url": { - "type": "string", - "description": "类型 Logo 地址。" + "description": "集成类型显示名,随请求语言变化。" }, "category": { "type": "string", - "description": "类型所属分类:`event.alert` 告警事件,`event.change` 变更事件,`im` IM 机器人,`webhook` 自定义 Webhook。", "enum": [ "event.alert", "event.change", "im", "webhook" - ] + ], + "description": "集成所属分类:`event.alert` 告警事件,`event.change` 变更事件,`im` IM 机器人,`webhook` 自定义 Webhook。" + }, + "name": { + "type": "string", + "description": "集成名称。" + }, + "description": { + "type": "string", + "description": "集成描述。" }, "status": { "type": "string", - "description": "该类型的平台状态:`enabled` 可正常使用;`disabled` 表示平台已停用该类型,`POST /integration/create` 与 `POST /integration/update` 会返回 `InvalidParameter`。", "enum": [ "enabled", "disabled" - ] + ], + "description": "状态:`enabled` 正常接收事件,`disabled` 已暂停。" }, - "supports_api_create": { + "ref_id": { + "type": "string", + "description": "来源引用 ID,账户级集成通常为 `a_`,旧记录也可能使用 `w_`;本接口不返回 `c_` 开头的专属集成。" + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "创建时间的 Unix 时间戳(秒)。" + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "最近更新时间的 Unix 时间戳(秒)。" + }, + "last_time": { + "type": "integer", + "format": "int64", + "description": "最近收到事件时间的 Unix 时间戳(秒),尚未收到事件时为 `0`。" + }, + "last_source_time": { + "type": "integer", + "format": "int64", + "description": "最近一次从上游工具收到事件的时间戳(Unix 秒),包含随后被丢弃、未成为告警的事件;尚未收到过事件时为 `0`。" + }, + "editable": { "type": "boolean", - "description": "该类型能否通过 `POST /integration/create` 创建。" - } - } - }, - "ListIntegrationTypesResponse": { - "type": "object", - "description": "集成类型列表的一页。", - "required": [ - "p", - "limit", - "total", - "items" - ], - "properties": { - "p": { + "description": "当前调用者是否通过集成对象权限校验;执行写操作还需集成中心管理权限。" + }, + "creator_id": { "type": "integer", - "description": "当前页码。" + "format": "int64", + "description": "创建集成的成员 ID。" }, - "limit": { + "updated_by": { "type": "integer", - "description": "当前每页条数。" + "format": "int64", + "description": "最近更新集成的成员 ID。" }, - "total": { + "no_editable": { + "type": "boolean", + "description": "只读标记;为 true 时公开接口不允许修改该集成。" + }, + "plugin_id": { "type": "integer", "format": "int64", - "description": "匹配的类型总数。" + "description": "集成类型的内部 ID;创建集成使用 `plugin_type`,不使用此 ID。" }, - "items": { - "type": "array", - "description": "当前页的集成类型。", - "items": { - "$ref": "#/components/schemas/IntegrationTypeItem" + "integration_key": { + "type": "string", + "description": "解密后的集成 Key,用于事件推送;未存储 Key 时为空字符串,与账户 `app_key` 不同。" + }, + "settings": { + "type": "object", + "additionalProperties": true, + "description": "存储的类型专属配置。已保存的密钥类值(密码、App Secret、Token、加密密钥、Webhook 地址、HTTP 拉取的 URL 与 Body、Headers、自定义 Body)返回 `******`,未设置的保持为空。" + }, + "test": { + "type": "object", + "description": "执行插件测试时返回的测试结果。", + "x-flashduty-preserve-absence": true, + "required": [ + "success", + "message" + ], + "properties": { + "success": { + "type": "boolean", + "description": "插件测试是否成功。" + }, + "message": { + "type": "string", + "description": "测试失败信息;成功时为空字符串。" + } } } } }, - "ListIntegrationsRequest": { + "CreateIntegrationRequest": { "type": "object", - "description": "查询集成列表的过滤参数。", + "description": "创建集成的请求体。", + "required": [ + "plugin_type" + ], "properties": { - "p": { - "type": "integer", - "minimum": 1, - "default": 1, - "description": "页码,从 1 开始。" - }, - "limit": { - "type": "integer", - "minimum": 1, - "maximum": 100, - "default": 100, - "description": "每页条数,默认 100,最大 100。" - }, - "orderby": { + "plugin_type": { "type": "string", - "description": "排序字段,默认 `created_at`;`plugin_type` 按底层插件排序。", - "enum": [ - "created_at", - "updated_at", - "name", - "plugin_type", - "status" - ] + "description": "集成类型,必须是 `POST /integration/type/list` 中 `supports_api_create: true` 的类型。", + "example": "standard.alert" }, - "category": { + "name": { "type": "string", - "description": "按大类过滤,多个值用逗号分隔。取值:`event.alert`(告警事件)、`event.change`(变更事件)、`im`(IM 机器人)、`webhook`(自定义 Webhook)。未知值不会报错,但匹配不到结果。" + "minLength": 2, + "maxLength": 49, + "description": "集成名称,非空时为 2–49 字符;不传或为空时使用集成类型名称。", + "example": "Prod metrics alerts" }, - "type": { + "description": { "type": "string", - "description": "已弃用,等同于 `plugin_type`(逗号分隔的类型标识,如 `prometheus.alert`、`zabbix.alert`)。同时传入 `plugin_type` 时忽略本字段。" + "maxLength": 499, + "description": "集成描述,最长 499 个字符。" }, - "plugin_type": { - "type": "string", - "description": "按集成类型过滤,多个值用逗号分隔,如 `standard.alert,prometheus.alert`;取值为 `POST /integration/type/list` 返回的 `plugin_type`。" + "team_id": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "所属团队 ID;不传或传 `0` 表示不设置团队,非零 ID 必须属于当前账户。", + "example": 1467226103121 }, - "status": { - "type": "string", - "description": "按状态过滤,多个值用逗号分隔:`enabled`(接收事件)、`disabled`(已暂停)。" + "settings": { + "type": "object", + "description": "集成类型专属配置,可传字段取决于 `plugin_type`。", + "additionalProperties": true }, - "name": { + "integration_key": { "type": "string", - "description": "按集成名称过滤,名称包含该文本即匹配。" - }, - "ref_ids": { - "type": "array", - "description": "按来源引用 ID 过滤;每个值必须以 `c_`(协作空间)、`a_`(账户)或 `w_` 开头。", - "items": { - "type": "string" - } + "minLength": 35, + "maxLength": 35, + "description": "可选预生成 Key,长度 35,末尾为账户 ID 对 1000 取余后补零至三位,且不能已被使用;不传时自动生成。" }, - "asc": { + "is_test": { "type": "boolean", - "description": "`true` 升序,`false` 降序。" + "description": "创建时执行插件测试;不传时为 false,测试结果查看返回的 `test.success`。" + } + } + }, + "CreateIntegrationResponse": { + "type": "object", + "description": "创建结果与集成 Key。", + "required": [ + "integration_id", + "integration_key" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "新建集成的 ID。", + "example": 6113996590131 }, - "is_my_team": { - "type": "boolean", - "description": "仅返回你所在团队拥有的集成。" + "integration_key": { + "type": "string", + "description": "用于事件推送的集成 Key,也可通过 `/integration/list` 和 `/integration/info` 查询。", + "example": "0123456789abcdef0123456789abcdef100" }, - "team_ids": { - "type": "array", - "description": "按团队 ID 过滤;与 `is_my_team` 同时使用时在其结果内进一步收窄。", - "items": { - "type": "integer", - "format": "int64" + "test": { + "type": "object", + "description": "执行插件测试时返回的测试结果。", + "x-flashduty-preserve-absence": true, + "required": [ + "success", + "message" + ], + "properties": { + "success": { + "type": "boolean", + "description": "插件测试是否成功。" + }, + "message": { + "type": "string", + "description": "测试失败信息;成功时为空字符串。" + } } } } }, - "IntegrationItem": { + "UpdateIntegrationRequest": { "type": "object", - "description": "公共集成列表项,包含完整存储配置;时间字段为 Unix 时间戳(秒)。", + "description": "更新集成的请求体;仅发送的字段会被修改。", "required": [ - "integration_id", - "team_id", - "plugin_type", - "plugin_type_name", - "category", - "name", - "description", - "status", - "ref_id", - "created_at", - "updated_at", - "last_time", - "editable", - "creator_id", - "updated_by", - "no_editable", - "plugin_id", - "integration_key", - "settings", - "data_source_id", - "account_id", - "exclusive_data_source_id" + "integration_id" ], "properties": { "integration_id": { "type": "integer", "format": "int64", - "description": "集成 ID,可作为 `integration_id` 传给其他 `/integration/*` 接口。" + "minimum": 1, + "description": "公共集成 ID,可从 `POST /integration/list` 获取。ID 不存在或属于协作空间专属集成时返回 `ResourceNotFound`。", + "example": 6113996590131 + }, + "name": { + "type": [ + "string", + "null" + ], + "minLength": 2, + "maxLength": 49, + "description": "新的集成名称,2–49 个字符。" + }, + "description": { + "type": [ + "string", + "null" + ], + "maxLength": 499, + "description": "新的集成描述,最长 499 个字符。" }, "team_id": { - "type": "integer", + "type": [ + "integer", + "null" + ], "format": "int64", - "description": "所属团队 ID;未归属团队时为 `0`。" + "minimum": 0, + "description": "新的所属团队 ID;传 `0` 表示清除团队归属。" }, - "plugin_type": { - "type": "string", - "description": "集成类型,例如 `standard.alert`、`zabbix.alert`。" + "settings": { + "type": "object", + "description": "替换类型专属配置;已识别的敏感字段不传或传 `******` 时保留原值,显式传空 headers 对象可清空 Headers。保留已存密钥时不能同时修改它的发送目标(如 `endpoint`、`url`、数据库主机或端口)。", + "additionalProperties": true }, - "plugin_type_name": { + "is_test": { + "type": "boolean", + "description": "提交 `settings` 时执行插件测试;仅更新名称、描述或团队时不执行测试。" + } + } + }, + "IntegrationLifecycleRequest": { + "type": "object", + "description": "指定要操作的集成。", + "required": [ + "integration_id" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "公共集成 ID,可从 `POST /integration/list` 获取。ID 不存在或属于协作空间专属集成时返回 `ResourceNotFound`。", + "example": 6113996590131 + } + } + }, + "RotateIntegrationKeyResponse": { + "type": "object", + "description": "新生成的集成 Key。", + "required": [ + "integration_key" + ], + "properties": { + "integration_key": { "type": "string", - "description": "集成类型显示名,随请求语言变化。" + "description": "新的集成 Key,旧 Key 立即失效;新 Key 也可通过 `/integration/list` 和 `/integration/info` 查询。", + "example": "0123456789abcdef0123456789abcdef100" + } + } + }, + "WorkItemAssignee": { + "description": "跟进事项的一名负责人。", + "properties": { + "id": { + "description": "成员 ID。`type` 为 `person` 时必填;`type` 为 `ai_sre` 时省略。", + "format": "int64", + "type": "integer" }, - "category": { - "type": "string", + "type": { + "description": "负责人类型:`person` 为成员,`ai_sre` 为账户的 AI SRE。", "enum": [ - "event.alert", - "event.change", - "im", - "webhook" + "person", + "ai_sre" ], - "description": "集成所属分类:`event.alert` 告警事件,`event.change` 变更事件,`im` IM 机器人,`webhook` 自定义 Webhook。" + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + }, + "AlertEvent": { + "type": "object", + "description": "一条原始告警事件,与接入管道接收和存储的结构一致。", + "required": [ + "event_status" + ], + "properties": { + "title": { + "type": "string", + "description": "事件标题。未提供 `title_rule` 时必填;两者共同决定告警标题的来源。" }, - "name": { + "title_rule": { "type": "string", - "description": "集成名称。" + "description": "标题模板,例如 `$service::$alertname`;`title` 为空时用它从 `labels` 生成标题。" }, "description": { "type": "string", - "description": "集成描述。" + "description": "事件描述,超过 2048 字符会被截断。" }, - "status": { + "alert_key": { + "type": "string", + "description": "用于将多个事件合并到同一告警的去重键。可为空:预览会随机生成一个键,因此不会发生合并。" + }, + "event_status": { "type": "string", "enum": [ - "enabled", - "disabled" + "Critical", + "Warning", + "Info", + "Ok" ], - "description": "状态:`enabled` 正常接收事件,`disabled` 已暂停。" + "description": "事件状态。`Critical`、`Warning`、`Info` 为触发事件,`Ok` 为恢复事件。" }, - "ref_id": { + "event_severity": { "type": "string", - "description": "来源引用 ID,账户级集成通常为 `a_`,旧记录也可能使用 `w_`;本接口不返回 `c_` 开头的专属集成。" + "enum": [ + "Critical", + "Warning", + "Info" + ], + "description": "触发事件携带的严重级别。预览会在触发事件上用 `event_status` 覆盖它。" }, - "created_at": { + "event_time": { "type": "integer", "format": "int64", - "description": "创建时间的 Unix 时间戳(秒)。" + "description": "Unix 时间戳(秒)。预览使用当前时间,传入值会被忽略。" }, - "updated_at": { - "type": "integer", - "format": "int64", - "description": "最近更新时间的 Unix 时间戳(秒)。" + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "事件标签集合,最多 50 项;键为标签名,值为字符串。" }, - "last_time": { + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertImage" + }, + "description": "事件附带的图片。" + } + } + }, + "EnrichmentPreviewEvent": { + "type": "object", + "description": "标签增强预览当时的事件。", + "required": [ + "title", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "执行到当前步骤时的事件标题。" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "执行到当前步骤时的标签集合。" + } + } + }, + "EnrichmentSample": { + "type": "object", + "description": "集成收到的一条原始事件,即进入标签增强之前的样子。", + "required": [ + "received_at", + "event", + "description_truncated" + ], + "properties": { + "received_at": { "type": "integer", "format": "int64", - "description": "最近收到事件时间的 Unix 时间戳(秒),尚未收到事件时为 `0`。" + "description": "集成收到该事件的时间戳(Unix 秒)。" }, - "editable": { + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "原始事件,尚未经过任何标签增强规则。" + }, + "description_truncated": { "type": "boolean", - "description": "当前调用者是否通过集成对象权限校验;执行写操作还需集成中心管理权限。" + "description": "存储的描述被截到样本大小上限时为 `true`。" }, - "creator_id": { + "dropped": { + "type": "boolean", + "description": "集成在事件成为告警之前将其丢弃时为 `true`;为 `false` 时不返回该字段。" + } + } + }, + "EnrichStep": { + "type": "object", + "description": "单条标签增强规则对事件做了什么。", + "required": [ + "index", + "kind", + "matched", + "skipped_reason", + "detail", + "added", + "removed", + "changed", + "mapping_row" + ], + "properties": { + "index": { "type": "integer", - "format": "int64", - "description": "创建集成的成员 ID。" + "description": "规则在 `rules` 中的位置,从 0 开始。" }, - "updated_by": { - "type": "integer", - "format": "int64", - "description": "最近更新集成的成员 ID。" + "kind": { + "type": "string", + "enum": [ + "extraction", + "composition", + "mapping", + "drop" + ], + "description": "执行过的规则类型。\n| 取值 | 含义 |\n|---|---|\n| `extraction` | 通过正则或 GJson 从事件 `title`、`description` 或 `labels.*` 中提取值并写入标签。 |\n| `composition` | 用模板渲染事件并把结果写入标签。 |\n| `mapping` | 从映射规则或外部映射 API 查询标签。 |\n| `drop` | 从告警中删除指定标签。 |" }, - "no_editable": { + "matched": { "type": "boolean", - "description": "只读标记;为 true 时公开接口不允许修改该集成。" - }, - "plugin_id": { - "type": "integer", - "format": "int64", - "description": "集成类型的内部 ID;创建集成使用 `plugin_type`,不使用此 ID。" + "description": "规则的 `if` 条件是否全部满足;`false` 表示规则没有改变任何标签。" }, - "integration_key": { + "skipped_reason": { "type": "string", - "description": "解密后的集成 Key,用于事件推送;未存储 Key 时为空字符串,与账户 `app_key` 不同。" + "description": "规则被跳过的原因:`condition_not_met`、`regex_not_matched`、`source_label_missing`、`mapping_row_not_found`、`result_label_exists` 或 `error`。规则正常执行时为空。" }, - "settings": { - "type": "object", - "additionalProperties": true, - "description": "存储的类型专属配置。已保存的密钥类值(密码、App Secret、Token、加密密钥、Webhook 地址、HTTP 拉取的 URL 与 Body、Headers、自定义 Body)返回 `******`,未设置的保持为空。" + "detail": { + "type": "string", + "description": "规则自身的细节:命中的映射行、渲染出的值,`skipped_reason` 为 `error` 时为错误信息。" }, - "data_source_id": { - "type": "integer", - "format": "int64", - "description": "旧 datasource ID,与 `integration_id` 相同。" + "added": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "规则新写入的标签;未新增时为 `null`。" }, - "account_id": { - "type": "integer", - "format": "int64", - "description": "集成所属账户 ID。" + "removed": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "规则删除的标签;未删除时为 `null`。" }, - "exclusive_data_source_id": { - "type": "integer", - "format": "int64", - "description": "旧接口兼容字段;此公共集成列表返回的值为 `0`。" + "changed": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "规则改写的标签,每个值为 `[旧值, 新值]` 两元数组;未改写时为 `null`。" + }, + "mapping_row": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "规则命中的映射行;不是映射规则或未命中时为 `null`。" } } }, - "ListIntegrationsResponse": { + "AlertPipelinePreviewEvent": { "type": "object", - "description": "集成列表的一页。", + "description": "告警处理预览当时的事件。", "required": [ - "p", - "limit", - "total", - "items" + "title", + "description", + "severity", + "labels" ], "properties": { - "p": { - "type": "integer", - "description": "当前页码。" + "title": { + "type": "string", + "description": "事件标题。" }, - "limit": { - "type": "integer", - "description": "当前每页条数。" + "description": { + "type": "string", + "description": "事件描述。" }, - "total": { - "type": "integer", - "format": "int64", - "description": "匹配的集成总数。" + "severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "此时事件携带的严重级别。" }, - "items": { - "type": "array", - "description": "当前页的集成。", - "items": { - "$ref": "#/components/schemas/IntegrationItem" - } + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "标签集合。" } } }, - "GetIntegrationRequest": { + "PipelineStep": { "type": "object", - "description": "指定一个集成。", + "description": "单条告警处理规则对事件做了什么。", "required": [ - "integration_id" + "index", + "kind", + "result", + "detail" ], "properties": { - "integration_id": { + "index": { "type": "integer", - "format": "int64", - "minimum": 1, - "description": "公共集成 ID,可从 `POST /integration/list` 获取。ID 不存在或属于协作空间专属集成时返回 `ResourceNotFound`。", - "example": 6113996590131 + "description": "规则在 `rules` 中的位置,从 0 开始。" + }, + "kind": { + "type": "string", + "enum": [ + "title_reset", + "description_reset", + "severity_reset", + "alert_drop", + "alert_inhibit" + ], + "description": "执行过的规则类型。\n| 取值 | 含义 |\n|---|---|\n| `title_reset` | 用规则模板改写标题。 |\n| `description_reset` | 用规则模板改写描述。 |\n| `severity_reset` | 把严重级别和状态重置为规则中的 `severity`。 |\n| `alert_drop` | 直接丢弃事件,不产生告警。 |\n| `alert_inhibit` | 存在匹配的活跃源告警时丢弃事件。 |" + }, + "result": { + "type": "string", + "enum": [ + "applied", + "not_matched", + "not_executed" + ], + "description": "规则结果:`applied`(改变了事件或终止了后续处理)、`not_matched`(`if` 条件没有全部满足)、`not_executed`(前面的规则已终止处理,或事件是恢复事件)。" + }, + "detail": { + "type": "string", + "description": "上述结果对应的 `condition_not_met`、`no_active_source_alert`、`inhibit_not_evaluated` 或 `recovery_event`;其他情况为结果值或错误信息。" } } }, - "IntegrationDetail": { + "AlertEmailPreviewSettings": { "type": "object", - "description": "公共集成详情,包含存储配置与解密 Key;时间字段为 Unix 时间戳(秒)。", - "required": [ - "integration_id", - "team_id", - "plugin_type", - "plugin_type_name", - "category", - "name", - "description", - "status", - "ref_id", - "created_at", - "updated_at", - "last_time", - "editable", - "creator_id", - "updated_by", - "no_editable", - "plugin_id", - "integration_key", - "settings" - ], + "description": "要预览的邮件集成配置,与保存接口接受的形状一致。", "properties": { - "integration_id": { - "type": "integer", - "format": "int64", - "description": "集成 ID,可作为 `integration_id` 传给其他 `/integration/*` 接口。" - }, - "team_id": { - "type": "integer", - "format": "int64", - "description": "所属团队 ID;未归属团队时为 `0`。" - }, - "plugin_type": { + "mode": { "type": "string", - "description": "集成类型,例如 `standard.alert`、`zabbix.alert`。" + "enum": [ + "alwaysTrigger", + "triggerByTitle", + "triggerOrCloseByRule" + ], + "description": "集成判定一封邮件归属的方式;省略时默认 `alwaysTrigger`。\n- `alwaysTrigger`:每封邮件都是独立告警,键随机生成。\n- `triggerByTitle`:每封邮件都是触发事件,告警键由邮件主题哈希得到。\n- `triggerOrCloseByRule`:由 `rules` 决定邮件是触发、关闭还是丢弃,未命中的由 `default` 处理。" }, - "plugin_type_name": { - "type": "string", - "description": "集成类型显示名,随请求语言变化。" + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertEmailRule" + }, + "description": "`mode` 为 `triggerOrCloseByRule` 时按顺序匹配的规则,每条都必须是非空对象,最多 50 条。" }, - "category": { + "default": { "type": "string", "enum": [ - "event.alert", - "event.change", - "im", - "webhook" + "trigger", + "discard" ], - "description": "集成所属分类:`event.alert` 告警事件,`event.change` 变更事件,`im` IM 机器人,`webhook` 自定义 Webhook。" - }, - "name": { - "type": "string", - "description": "集成名称。" - }, - "description": { + "description": "`mode` 为 `triggerOrCloseByRule` 且没有规则命中时的处理方式:`trigger` 转为触发事件,`discard` 丢弃。" + } + } + }, + "AlertEmailRule": { + "type": "object", + "description": "匹配一封邮件并从中提取告警键的规则。", + "required": [ + "type", + "extract_from", + "extract_pattern", + "filters" + ], + "properties": { + "type": { "type": "string", - "description": "集成描述。" + "enum": [ + "trigger", + "close" + ], + "description": "`trigger` 表示命中的邮件转为触发事件,`close` 转为恢复事件。" }, - "status": { + "extract_from": { "type": "string", "enum": [ - "enabled", - "disabled" + "title", + "description" ], - "description": "状态:`enabled` 正常接收事件,`disabled` 已暂停。" + "description": "告警键从邮件的哪一部分提取:`title` 或 `description`。取 `description` 时依次搜索正文纯文本、带表格的正文、描述。" }, - "ref_id": { + "extract_pattern": { "type": "string", - "description": "来源引用 ID,账户级集成通常为 `a_`,旧记录也可能使用 `w_`;本接口不返回 `c_` 开头的专属集成。" - }, - "created_at": { - "type": "integer", - "format": "int64", - "description": "创建时间的 Unix 时间戳(秒)。" - }, - "updated_at": { - "type": "integer", - "format": "int64", - "description": "最近更新时间的 Unix 时间戳(秒)。" - }, - "last_time": { - "type": "integer", - "format": "int64", - "description": "最近收到事件时间的 Unix 时间戳(秒),尚未收到事件时为 `0`。" - }, - "editable": { - "type": "boolean", - "description": "当前调用者是否通过集成对象权限校验;执行写操作还需集成中心管理权限。" + "description": "提取告警键的正则表达式,捕获到的分组用 `,` 拼接为键来源;没有捕获到任何内容时回退为邮件主题。" }, - "creator_id": { - "type": "integer", - "format": "int64", - "description": "创建集成的成员 ID。" + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterCondition" + }, + "description": "邮件必须全部满足的条件;传 `[]` 表示匹配所有邮件。" + } + } + }, + "AlertEmailPreviewEmail": { + "type": "object", + "description": "要预览的邮件内容。", + "properties": { + "subject": { + "type": "string", + "description": "邮件主题。" }, - "updated_by": { - "type": "integer", - "format": "int64", - "description": "最近更新集成的成员 ID。" + "body": { + "type": "string", + "description": "邮件正文:以 `<` 开头按 HTML 处理,否则按纯文本处理。" }, - "no_editable": { - "type": "boolean", - "description": "只读标记;为 true 时公开接口不允许修改该集成。" + "from": { + "type": "string", + "description": "发件人地址。" }, - "plugin_id": { - "type": "integer", - "format": "int64", - "description": "集成类型的内部 ID;创建集成使用 `plugin_type`,不使用此 ID。" + "eml": { + "type": "string", + "description": "整封邮件文件(`.eml`)的 base64 内容。提供后它会替代 `subject`、`body` 和 `from`,并按 SMTP 服务端的解析方式解析。" + } + } + }, + "AlertEmailPreviewEvent": { + "type": "object", + "description": "这封邮件会产生的告警事件。", + "required": [ + "title", + "description", + "event_status", + "event_severity", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "事件标题。" }, - "integration_key": { + "description": { "type": "string", - "description": "解密后的集成 Key,用于事件推送;未存储 Key 时为空字符串,与账户 `app_key` 不同。" + "description": "事件描述。" }, - "settings": { - "type": "object", - "additionalProperties": true, - "description": "存储的类型专属配置。已保存的密钥类值(密码、App Secret、Token、加密密钥、Webhook 地址、HTTP 拉取的 URL 与 Body、Headers、自定义 Body)返回 `******`,未设置的保持为空。" + "event_status": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "这封邮件产生的事件状态。" }, - "test": { - "type": "object", - "description": "执行插件测试时返回的测试结果。", - "x-flashduty-preserve-absence": true, - "required": [ - "success", - "message" + "event_severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" ], - "properties": { - "success": { - "type": "boolean", - "description": "插件测试是否成功。" - }, - "message": { - "type": "string", - "description": "测试失败信息;成功时为空字符串。" - } - } + "description": "触发事件的严重级别;恢复事件为空。" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "从邮件中提取的标签:正文、发件人、收件人和主题都会以标签形式暴露。" } } }, - "CreateIntegrationRequest": { + "AlertEmailPreviewParsed": { "type": "object", - "description": "创建集成的请求体。", + "description": "转换时实际读到的邮件内容。", "required": [ - "plugin_type" + "subject", + "from", + "body", + "body_text" ], "properties": { - "plugin_type": { + "subject": { "type": "string", - "description": "集成类型,必须是 `POST /integration/type/list` 中 `supports_api_create: true` 的类型。", - "example": "standard.alert" + "description": "解析后的邮件主题。" }, - "name": { + "from": { "type": "string", - "minLength": 2, - "maxLength": 49, - "description": "集成名称,非空时为 2–49 字符;不传或为空时使用集成类型名称。", - "example": "Prod metrics alerts" + "description": "从邮件中取到的发件人地址。" }, - "description": { + "body": { "type": "string", - "maxLength": 499, - "description": "集成描述,最长 499 个字符。" - }, - "team_id": { - "type": "integer", - "format": "int64", - "minimum": 0, - "description": "所属团队 ID;不传或传 `0` 表示不设置团队,非零 ID 必须属于当前账户。", - "example": 1467226103121 - }, - "settings": { - "type": "object", - "description": "集成类型专属配置,可传字段取决于 `plugin_type`。", - "additionalProperties": true + "description": "转换使用的正文:存在 HTML 部分时用它,否则用纯文本部分。" }, - "integration_key": { + "body_text": { "type": "string", - "minLength": 35, - "maxLength": 35, - "description": "可选预生成 Key,长度 35,末尾为账户 ID 对 1000 取余后补零至三位,且不能已被使用;不传时自动生成。" - }, - "is_test": { - "type": "boolean", - "description": "创建时执行插件测试;不传时为 false,测试结果查看返回的 `test.success`。" + "description": "纯文本正文;从描述中提取告警键时优先在这里搜索。" } } }, - "CreateIntegrationResponse": { + "EnrichmentPreviewRequest": { "type": "object", - "description": "创建结果与集成 Key。", + "description": "`POST /enrichment/preview` 的请求体。", "required": [ "integration_id", - "integration_key" + "event" ], "properties": { "integration_id": { "type": "integer", "format": "int64", - "description": "新建集成的 ID。", - "example": 6113996590131 + "minimum": 1, + "description": "预览所依据的集成 ID;发送的规则不会被保存。" }, - "integration_key": { - "type": "string", - "description": "用于事件推送的集成 Key,也可通过 `/integration/list` 和 `/integration/info` 查询。", - "example": "0123456789abcdef0123456789abcdef100" + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/EnrichRule" + }, + "description": "按顺序尝试的标签增强规则,最多 50 条;不会使用该集成已存的规则。" }, - "test": { - "type": "object", - "description": "执行插件测试时返回的测试结果。", - "x-flashduty-preserve-absence": true, - "required": [ - "success", - "message" - ], - "properties": { - "success": { - "type": "boolean", - "description": "插件测试是否成功。" - }, - "message": { - "type": "string", - "description": "测试失败信息;成功时为空字符串。" - } - } + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "要跑规则的事件。" } } }, - "UpdateIntegrationRequest": { + "EnrichmentPreviewResponse": { "type": "object", - "description": "更新集成的请求体;仅发送的字段会被修改。", + "description": "标签增强预览的结果。", + "required": [ + "before", + "after", + "steps" + ], + "properties": { + "before": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "事件进入时的样子。" + }, + "after": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "规则执行后的事件,触发事件已按接入方式渲染 `[TPL]` 标签、标题和描述。" + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichStep" + }, + "description": "每条规则一项,按执行顺序排列。" + } + } + }, + "EnrichmentSampleListRequest": { + "type": "object", + "description": "`POST /enrichment/sample/list` 的请求体。", "required": [ "integration_id" ], @@ -36269,97 +37399,182 @@ "type": "integer", "format": "int64", "minimum": 1, - "description": "公共集成 ID,可从 `POST /integration/list` 获取。ID 不存在或属于协作空间专属集成时返回 `ResourceNotFound`。", - "example": 6113996590131 - }, - "name": { - "type": [ - "string", - "null" - ], - "minLength": 2, - "maxLength": 49, - "description": "新的集成名称,2–49 个字符。" - }, - "description": { - "type": [ - "string", - "null" - ], - "maxLength": 499, - "description": "新的集成描述,最长 499 个字符。" - }, - "team_id": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0, - "description": "新的所属团队 ID;传 `0` 表示清除团队归属。" - }, - "settings": { - "type": "object", - "description": "替换类型专属配置;已识别的敏感字段不传或传 `******` 时保留原值,显式传空 headers 对象可清空 Headers。保留已存密钥时不能同时修改它的发送目标(如 `endpoint`、`url`、数据库主机或端口)。", - "additionalProperties": true - }, - "is_test": { - "type": "boolean", - "description": "提交 `settings` 时执行插件测试;仅更新名称、描述或团队时不执行测试。" + "description": "要查看最近原始事件的集成 ID。" } } }, - "IntegrationLifecycleRequest": { + "EnrichmentSampleListResponse": { "type": "object", - "description": "指定要操作的集成。", + "description": "某个集成最近的原始事件。", "required": [ - "integration_id" + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichmentSample" + }, + "description": "样本列表,最新的在前;尚未收到事件时为空。" + } + } + }, + "AlertPipelinePreviewRequest": { + "type": "object", + "description": "`POST /alert/pipeline/preview` 的请求体。", + "required": [ + "integration_id", + "event" ], "properties": { "integration_id": { "type": "integer", "format": "int64", "minimum": 1, - "description": "公共集成 ID,可从 `POST /integration/list` 获取。ID 不存在或属于协作空间专属集成时返回 `ResourceNotFound`。", - "example": 6113996590131 + "description": "预览所用的集成 ID;该集成已存的标签增强会先执行。" + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertPipeline" + }, + "description": "按顺序尝试的告警处理规则,最多 50 条;不会使用该集成已存的处理规则。" + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "要跑规则的事件。" } } }, - "RotateIntegrationKeyResponse": { + "AlertPipelinePreviewResponse": { "type": "object", - "description": "新生成的集成 Key。", + "description": "告警处理预览的结果。", "required": [ - "integration_key" + "is_recovery", + "before", + "after", + "dropped", + "inhibited", + "steps" ], "properties": { - "integration_key": { - "type": "string", - "description": "新的集成 Key,旧 Key 立即失效;新 Key 也可通过 `/integration/list` 和 `/integration/info` 查询。", - "example": "0123456789abcdef0123456789abcdef100" + "is_recovery": { + "type": "boolean", + "description": "事件是恢复事件时为 `true`:接入会直接关闭告警,不执行处理规则。" + }, + "before": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "事件进入时的样子。" + }, + "after": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "规则执行后、通知模板渲染出的事件。" + }, + "dropped": { + "type": "boolean", + "description": "某条规则丢弃了该事件、不会产生告警时为 `true`。" + }, + "inhibited": { + "type": "boolean", + "description": "某条规则因存在匹配的活跃源告警而抑制了该事件时为 `true`。" + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PipelineStep" + }, + "description": "每条规则一项,按执行顺序排列。" } } }, - "WorkItemAssignee": { - "description": "跟进事项的一名负责人。", + "AlertEmailPreviewRequest": { + "type": "object", + "description": "`POST /alert/email/preview` 的请求体。", + "required": [ + "settings", + "email" + ], "properties": { - "id": { - "description": "成员 ID。`type` 为 `person` 时必填;`type` 为 `ai_sre` 时省略。", + "integration_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "提供初始配置的邮件集成 ID。传 `0` 或不传等价于控制台在新建页面、集成尚不存在时的场景。" }, - "type": { - "description": "负责人类型:`person` 为成员,`ai_sre` 为账户的 AI SRE。", - "enum": [ - "person", - "ai_sre" - ], - "type": "string" + "settings": { + "$ref": "#/components/schemas/AlertEmailPreviewSettings", + "description": "要预览的配置,按保存接口的规则校验。" + }, + "email": { + "$ref": "#/components/schemas/AlertEmailPreviewEmail", + "description": "要转换的邮件。" } - }, + } + }, + "AlertEmailPreviewResponse": { + "type": "object", + "description": "配置对这封邮件的判定,以及转换实际读到的内容。", "required": [ - "type" + "result", + "matched_rule", + "key_source", + "key_fallback", + "alert_key", + "event", + "email" ], - "type": "object" + "properties": { + "result": { + "type": "string", + "enum": [ + "trigger", + "close", + "discard" + ], + "description": "配置对这封邮件的判定:`trigger`(触发事件)、`close`(恢复事件)、`discard`(丢弃)。" + }, + "matched_rule": { + "type": [ + "integer", + "null" + ], + "description": "命中的规则下标,从 0 开始;没有规则命中时为 `null`,`alwaysTrigger` 与 `triggerByTitle` 模式下始终为 `null`。" + }, + "key_source": { + "type": "string", + "description": "告警键的哈希来源。`alwaysTrigger` 模式下每封邮件各自成为告警,或被丢弃时为空。" + }, + "key_fallback": { + "type": "boolean", + "description": "规则的正则没有捕获到内容、改用邮件主题作为键来源时为 `true`。" + }, + "alert_key": { + "type": "string", + "description": "`key_source` 的哈希值。`alwaysTrigger` 模式下每封邮件使用随机键,此字段为空。" + }, + "event": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewEvent" + }, + { + "type": "null" + } + ], + "description": "这封邮件产生的事件;邮件被丢弃时为 `null`。" + }, + "email": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewParsed" + }, + { + "type": "null" + } + ], + "description": "转换实际读到的邮件内容;无法解析邮件时为 `null`。" + } + } } } } diff --git a/api-reference/openapi.en.json b/api-reference/openapi.en.json index 355ada1e..30cebd33 100644 --- a/api-reference/openapi.en.json +++ b/api-reference/openapi.en.json @@ -23651,6 +23651,14 @@ "type": "string", "description": "Display alias for the entry; not used when sending." }, + "disable_at": { + "type": "boolean", + "description": "Turn @-mentions off for this robot: `true` disables them, `false` forces them on. Omitted keeps the legacy behaviour — on for WeCom, and for other robot types only when `user_schema_id` is set." + }, + "user_schema_id": { + "type": "string", + "description": "ID of the user mapping schema (24-character ObjectID hex) the robot resolves @-mentions through. Required by Feishu robots that mention users; stored lowercased." + }, "data_source_id": { "type": "integer", "format": "int64", @@ -34000,6 +34008,11 @@ "format": "int64", "description": "Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet." }, + "last_source_time": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds of the most recent event received from the upstream tool, including events dropped before they became alerts. `0` when none has arrived yet." + }, "editable": { "type": "boolean", "description": "Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage." @@ -34185,6 +34198,11 @@ "format": "int64", "description": "Unix timestamp in seconds of the most recent event received. `0` when no event has arrived yet." }, + "last_source_time": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds of the most recent event received from the upstream tool, including events dropped before they became alerts. `0` when none has arrived yet." + }, "editable": { "type": "boolean", "description": "Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage." @@ -36229,6 +36247,687 @@ "$ref": "#/components/schemas/RumDashboardTextViz" } ] + }, + "AlertEvent": { + "type": "object", + "description": "One raw alert event, in the shape the ingestion pipeline receives and stores.", + "required": [ + "event_status" + ], + "properties": { + "title": { + "type": "string", + "description": "Event title. Required unless `title_rule` is set; the two are the source of the alert title." + }, + "title_rule": { + "type": "string", + "description": "Title template such as `$service::$alertname`, built from `labels` when `title` is empty." + }, + "description": { + "type": "string", + "description": "Event description, truncated to 2048 characters." + }, + "alert_key": { + "type": "string", + "description": "Deduplication key that merges events into one alert. Empty is allowed: the preview mints a random key, so nothing is merged." + }, + "event_status": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "Event status. `Critical`, `Warning` and `Info` are firing events; `Ok` is a recovery." + }, + "event_severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ], + "description": "Severity carried by a firing event. The preview overwrites it with `event_status` for firing events." + }, + "event_time": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds. The preview stamps the current time, so the value sent is ignored." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Event labels. Up to 50 entries; keys are label names, values strings." + }, + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertImage" + }, + "description": "Images attached to the event." + } + } + }, + "EnrichmentPreviewEvent": { + "type": "object", + "description": "The event as the enrichment preview saw it.", + "required": [ + "title", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "Event title after the steps applied so far." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Label set after the steps applied so far." + } + } + }, + "EnrichmentSample": { + "type": "object", + "description": "One raw event an integration received, as it entered enrichment.", + "required": [ + "received_at", + "event", + "description_truncated" + ], + "properties": { + "received_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds of when the integration received the event." + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "The raw event, before any enrichment rule ran." + }, + "description_truncated": { + "type": "boolean", + "description": "`true` when the stored description was cut to the sample size limit." + }, + "dropped": { + "type": "boolean", + "description": "`true` when the integration discarded the event before it became an alert. Omitted when `false`." + } + } + }, + "EnrichStep": { + "type": "object", + "description": "What one enrichment rule did to the event.", + "required": [ + "index", + "kind", + "matched", + "skipped_reason", + "detail", + "added", + "removed", + "changed", + "mapping_row" + ], + "properties": { + "index": { + "type": "integer", + "description": "Zero-based position of the rule in `rules`." + }, + "kind": { + "type": "string", + "enum": [ + "extraction", + "composition", + "mapping", + "drop" + ], + "description": "Rule type that ran.\n| Value | Meaning |\n|---|---|\n| `extraction` | Extract a value from the alert's `title`, `description` or a `labels.*` key and write it to a label. |\n| `composition` | Render a template against the event and write the result to a label. |\n| `mapping` | Look up labels from a mapping schema or an external mapping API. |\n| `drop` | Remove the listed labels from the alert. |" + }, + "matched": { + "type": "boolean", + "description": "Whether the rule's `if` conditions all matched. `false` means the rule changed nothing." + }, + "skipped_reason": { + "type": "string", + "description": "Why the rule was skipped: `condition_not_met`, `regex_not_matched`, `source_label_missing`, `mapping_row_not_found`, `result_label_exists` or `error`. Empty when the rule ran." + }, + "detail": { + "type": "string", + "description": "Rule-specific detail: the matched mapping row, the rendered value, or the error message when `skipped_reason` is `error`." + }, + "added": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "Labels the rule wrote that were not there before. `null` when it added none." + }, + "removed": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Labels the rule deleted. `null` when it removed none." + }, + "changed": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "Labels the rule rewrote, each as a `[old_value, new_value]` pair. `null` when it rewrote none." + }, + "mapping_row": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "The mapping row the rule matched. `null` for a rule that is not a mapping rule or matched no row." + } + } + }, + "AlertPipelinePreviewEvent": { + "type": "object", + "description": "The event as the pipeline preview saw it.", + "required": [ + "title", + "description", + "severity", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "Event title." + }, + "description": { + "type": "string", + "description": "Event description." + }, + "severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "Severity the event carried at this point." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Label set." + } + } + }, + "PipelineStep": { + "type": "object", + "description": "What one alert processing rule did to the event.", + "required": [ + "index", + "kind", + "result", + "detail" + ], + "properties": { + "index": { + "type": "integer", + "description": "Zero-based position of the rule in `rules`." + }, + "kind": { + "type": "string", + "enum": [ + "title_reset", + "description_reset", + "severity_reset", + "alert_drop", + "alert_inhibit" + ], + "description": "Rule type that ran.\n| Value | Meaning |\n|---|---|\n| `title_reset` | Rewrote the title from the rule's template. |\n| `description_reset` | Rewrote the description from the rule's template. |\n| `severity_reset` | Reset the severity and status to the rule's `severity`. |\n| `alert_drop` | Discarded the event; no alert is created. |\n| `alert_inhibit` | Discarded the event while a matching source alert is active. |" + }, + "result": { + "type": "string", + "enum": [ + "applied", + "not_matched", + "not_executed" + ], + "description": "Outcome of the rule: `applied` (it changed the event or stopped the pipeline), `not_matched` (its `if` conditions did not all match), or `not_executed` (an earlier rule stopped the pipeline, or the event is a recovery)." + }, + "detail": { + "type": "string", + "description": "`condition_not_met`, `no_active_source_alert`, `inhibit_not_evaluated` or `recovery_event` for those outcomes; otherwise the resulting value or the error message." + } + } + }, + "AlertEmailPreviewSettings": { + "type": "object", + "description": "Email integration settings to preview, in the shape the save endpoint accepts.", + "properties": { + "mode": { + "type": "string", + "enum": [ + "alwaysTrigger", + "triggerByTitle", + "triggerOrCloseByRule" + ], + "description": "How the integration decides what an email becomes. Omitted defaults to `alwaysTrigger`.\n- `alwaysTrigger`: every email becomes its own alert, keyed randomly.\n- `triggerByTitle`: every email becomes a firing event whose alert key is hashed from the subject.\n- `triggerOrCloseByRule`: `rules` decide whether an email triggers, closes or is discarded, and `default` handles the rest." + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertEmailRule" + }, + "description": "Rules tried in order when `mode` is `triggerOrCloseByRule`; each entry must be a non-empty object. At most 50." + }, + "default": { + "type": "string", + "enum": [ + "trigger", + "discard" + ], + "description": "What happens to an email that matches no rule when `mode` is `triggerOrCloseByRule`: `trigger` turns it into a firing event, `discard` drops it." + } + } + }, + "AlertEmailRule": { + "type": "object", + "description": "One rule that matches an email and extracts the alert key from it.", + "required": [ + "type", + "extract_from", + "extract_pattern", + "filters" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "trigger", + "close" + ], + "description": "`trigger` turns a matching email into a firing event, `close` into a recovery event." + }, + "extract_from": { + "type": "string", + "enum": [ + "title", + "description" + ], + "description": "Which part of the email the alert key is extracted from: `title` or `description`. For `description` the body text is searched first, then the body text with tables, then the description." + }, + "extract_pattern": { + "type": "string", + "description": "Regular expression the key is extracted with; the captured groups are joined by `,` to form the key source. A pattern that captures nothing falls back to the subject." + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterCondition" + }, + "description": "AND conditions the email must match for the rule to apply. Send `[]` to match every email." + } + } + }, + "AlertEmailPreviewEmail": { + "type": "object", + "description": "The email to run the preview over.", + "properties": { + "subject": { + "type": "string", + "description": "Email subject." + }, + "body": { + "type": "string", + "description": "Email body: HTML when it starts with `<`, otherwise plain text." + }, + "from": { + "type": "string", + "description": "Sender address." + }, + "eml": { + "type": "string", + "description": "A whole email file (`.eml`) as base64. When set it stands in for `subject`, `body` and `from` and is parsed the way the SMTP server parses mail." + } + } + }, + "AlertEmailPreviewEvent": { + "type": "object", + "description": "The alert event the email would have produced.", + "required": [ + "title", + "description", + "event_status", + "event_severity", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "Event title." + }, + "description": { + "type": "string", + "description": "Event description." + }, + "event_status": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "Status of the event this email produces." + }, + "event_severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ], + "description": "Severity of a firing event; empty for a recovery." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Labels taken from the email: the body, sender, recipients and subject are exposed as labels." + } + } + }, + "AlertEmailPreviewParsed": { + "type": "object", + "description": "The email as the conversion read it.", + "required": [ + "subject", + "from", + "body", + "body_text" + ], + "properties": { + "subject": { + "type": "string", + "description": "Subject as the parser decoded it." + }, + "from": { + "type": "string", + "description": "Sender address taken from the email." + }, + "body": { + "type": "string", + "description": "Body the conversion used: the HTML part when there is one, otherwise the text part." + }, + "body_text": { + "type": "string", + "description": "Body as plain text; a key extracted from the description is looked for here first." + } + } + }, + "EnrichmentPreviewRequest": { + "type": "object", + "description": "Request body of `POST /enrichment/preview`.", + "required": [ + "integration_id", + "event" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "Integration whose context the preview runs in. The rules you send are not saved." + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/EnrichRule" + }, + "description": "Enrichment rules to try, in order. At most 50. The integration's stored rules are not used." + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "The event to run the rules over." + } + } + }, + "EnrichmentPreviewResponse": { + "type": "object", + "description": "Result of the enrichment preview.", + "required": [ + "before", + "after", + "steps" + ], + "properties": { + "before": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "The event as it arrived." + }, + "after": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "The event after the rules ran, with the `[TPL]` labels, title and description of a firing event rendered." + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichStep" + }, + "description": "One entry per rule, in the order they ran." + } + } + }, + "EnrichmentSampleListRequest": { + "type": "object", + "description": "Request body of `POST /enrichment/sample/list`.", + "required": [ + "integration_id" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "Integration whose recent raw events to list." + } + } + }, + "EnrichmentSampleListResponse": { + "type": "object", + "description": "Recent raw events of one integration.", + "required": [ + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichmentSample" + }, + "description": "Samples, newest first. Empty when no event has arrived yet." + } + } + }, + "AlertPipelinePreviewRequest": { + "type": "object", + "description": "Request body of `POST /alert/pipeline/preview`.", + "required": [ + "integration_id", + "event" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "Integration whose saved enrichment runs first and whose pipeline context the preview uses." + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertPipeline" + }, + "description": "Alert processing rules to try, in order. At most 50. The integration's stored pipeline is not used." + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "The event to run the rules over." + } + } + }, + "AlertPipelinePreviewResponse": { + "type": "object", + "description": "Result of the pipeline preview.", + "required": [ + "is_recovery", + "before", + "after", + "dropped", + "inhibited", + "steps" + ], + "properties": { + "is_recovery": { + "type": "boolean", + "description": "`true` when the event is a recovery event: ingestion closes the alert without running the pipeline." + }, + "before": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "The event as it arrived." + }, + "after": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "The event as notification templates would render it once the rules ran." + }, + "dropped": { + "type": "boolean", + "description": "`true` when a rule dropped the event, so no alert would be created." + }, + "inhibited": { + "type": "boolean", + "description": "`true` when a rule inhibited the event because a matching source alert is active." + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PipelineStep" + }, + "description": "One entry per rule, in the order they ran." + } + } + }, + "AlertEmailPreviewRequest": { + "type": "object", + "description": "Request body of `POST /alert/email/preview`.", + "required": [ + "settings", + "email" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Email integration whose saved settings seed the preview. `0` or omitted is what the console sends on the create page, before the integration exists." + }, + "settings": { + "$ref": "#/components/schemas/AlertEmailPreviewSettings", + "description": "Settings to preview. They are validated the way the save endpoint validates them." + }, + "email": { + "$ref": "#/components/schemas/AlertEmailPreviewEmail", + "description": "The email to convert." + } + } + }, + "AlertEmailPreviewResponse": { + "type": "object", + "description": "How the settings treated the email, plus what the conversion read.", + "required": [ + "result", + "matched_rule", + "key_source", + "key_fallback", + "alert_key", + "event", + "email" + ], + "properties": { + "result": { + "type": "string", + "enum": [ + "trigger", + "close", + "discard" + ], + "description": "What the settings make of this email: `trigger` (a firing event), `close` (a recovery event) or `discard` (dropped)." + }, + "matched_rule": { + "type": [ + "integer", + "null" + ], + "description": "Zero-based index of the rule that matched. `null` when no rule matched, and always `null` in `alwaysTrigger` and `triggerByTitle` modes." + }, + "key_source": { + "type": "string", + "description": "What the alert key was hashed from. Empty when every email is its own alert (`alwaysTrigger`) or the email is discarded." + }, + "key_fallback": { + "type": "boolean", + "description": "`true` when the rule's pattern captured nothing and the subject was used as the key source." + }, + "alert_key": { + "type": "string", + "description": "Hash of `key_source`. Empty in `alwaysTrigger` mode, where each email gets a random key." + }, + "event": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewEvent" + }, + { + "type": "null" + } + ], + "description": "The event the email produces. `null` when the email is discarded." + }, + "email": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewParsed" + }, + { + "type": "null" + } + ], + "description": "What the conversion read from the email. `null` when the email could not be parsed." + } + } } }, "securitySchemes": { @@ -74873,6 +75572,522 @@ } } } + }, + "/alert/email/preview": { + "post": { + "operationId": "alert-read-email-preview", + "summary": "Preview email-to-alert conversion", + "description": "Run unsaved email integration settings over one email, the way ingestion would.", + "tags": [ + "On-call/Integrations" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Nothing is written: no integration, alert or event is created or changed.\n- `integration_id` seeds the preview with the integration's stored address prefix; the address itself is never used, so the preview works on the create page too.\n- `settings` passes the same validator the save endpoint runs, so an unsupported `mode`, rule `type`, `extract_from` or an invalid `extract_pattern` fails with `InvalidParameter` before the email is parsed.\n- When `eml` is set the message is parsed as a mail file, within the SMTP message size limit, and `email` in the response shows what the parser read.\n- `event` is `null` when the settings discard the email, and `email` is `null` when the message cannot be parsed.\n- In `alwaysTrigger` mode every email becomes its own alert: `alert_key` and `key_source` come back empty.", + "href": "/en/api-reference/on-call/integrations/alert-read-email-preview", + "metadata": { + "sidebarTitle": "Preview email-to-alert conversion" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertEmailPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "result": "trigger", + "matched_rule": 0, + "key_source": "checkout 5xx rate above 2%", + "key_fallback": false, + "alert_key": "8f14e45fceea167a5a36dedd4bea2543", + "event": { + "title": "[ALERT] checkout 5xx rate above 2%", + "description": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "event_status": "Critical", + "event_severity": "Critical", + "labels": { + "from": "alerts@acme.example.com", + "subject": "[ALERT] checkout 5xx rate above 2%" + } + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "from": "alerts@acme.example.com", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "body_text": "The checkout service 5xx rate is 3.4% over the last 5 minutes." + } + } + } + } + } + }, + "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/AlertEmailPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "settings": { + "mode": "triggerOrCloseByRule", + "rules": [ + { + "type": "trigger", + "extract_from": "title", + "extract_pattern": "^\\[ALERT\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[ALERT]/" + ] + } + ] + }, + { + "type": "close", + "extract_from": "title", + "extract_pattern": "^\\[OK\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[OK]/" + ] + } + ] + } + ], + "default": "discard" + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "from": "alerts@acme.example.com" + } + } + } + } + } + } + }, + "/alert/pipeline/preview": { + "post": { + "operationId": "alert-read-pipeline-preview", + "summary": "Preview alert pipeline processing", + "description": "Run unsaved alert processing rules over one event, the way ingestion would.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Nothing is saved and no alert or event is created.\n- The integration's saved enrichment rules run first, then your `rules` in order, against the enriched event.\n- A recovery (`Ok`) event closes the alert without running the pipeline: `is_recovery` is `true` and every step comes back `not_executed` with detail `recovery_event`.\n- `dropped` and `inhibited` report which rule stopped the event: `alert_drop` discards it, `alert_inhibit` discards it while a matching source alert is active. Rules after that one are `not_executed`.\n- When no rule matches, `after` is the event as the notification templates render it, so the preview shows what the channel would deliver.", + "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-preview", + "metadata": { + "sidebarTitle": "Preview alert pipeline processing" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelinePreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "is_recovery": false, + "before": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "after": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "dropped": false, + "inhibited": false, + "steps": [ + { + "index": 0, + "kind": "severity_reset", + "result": "not_matched", + "detail": "condition_not_met" + }, + { + "index": 1, + "kind": "alert_drop", + "result": "not_matched", + "detail": "condition_not_met" + } + ] + } + } + } + } + }, + "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/AlertPipelinePreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "severity_reset", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "test" + ] + } + ], + "settings": { + "severity": "Info" + } + }, + { + "kind": "alert_drop", + "if": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/.*noise.*/" + ] + } + ], + "settings": {} + } + ], + "event": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "event_status": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + } + } + } + } + } + } + }, + "/enrichment/preview": { + "post": { + "operationId": "enrichment-read-preview", + "summary": "Preview enrichment rule results", + "description": "Run unsaved enrichment rules over one event, the way ingestion would.", + "tags": [ + "On-call/Alert enrichment" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Nothing is saved and no alert or event is created.\n- `integration_id` must be an integration of the account, and the caller must be allowed to read it.\n- A `mapping` rule with `mapping_type` = `api` calls the account's mapping API with its stored headers, so the request also needs permission to edit the integration; without it the call fails.\n- `before` is the event as it arrived, `after` is the event after the rules; `steps` explains every rule — whether its conditions matched, why it was skipped, and which labels it added, removed or rewrote.\n- A firing event is rendered the way ingestion does after enrichment, so `[TPL]` labels, title and description in `after` are the final ones.\n- `if` keys must come from the alert or change event vocabulary (`title`, `description`, `labels.`, ...); other keys return `InvalidParameter`.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-preview", + "metadata": { + "sidebarTitle": "Preview enrichment rule results" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "before": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + } + }, + "after": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7", + "service_name": "checkout" + } + }, + "steps": [ + { + "index": 0, + "kind": "extraction", + "matched": true, + "skipped_reason": "", + "detail": "checkout", + "added": { + "service_name": "checkout" + }, + "removed": null, + "changed": null, + "mapping_row": null + } + ] + } + } + } + } + }, + "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/EnrichmentPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "extraction", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "prod" + ] + } + ], + "settings": { + "source_field": "labels.host", + "result_label": "service_name", + "pattern": "^(?P[a-z0-9-]+)-\\d+$", + "override": false + } + } + ], + "event": { + "title": "CPU usage 94% on checkout-7", + "description": "CPU usage above 90% for 5 minutes.", + "event_status": "Critical", + "labels": { + "env": "prod", + "host": "checkout-7", + "check": "cpu" + } + } + } + } + } + } + } + }, + "/enrichment/sample/list": { + "post": { + "operationId": "enrichment-sample-read-list", + "summary": "List recent event samples", + "description": "List the raw events an integration received most recently, newest first.", + "tags": [ + "On-call/Alert enrichment" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Samples are the events as they entered enrichment, so they show exactly the labels your rules match on.\n- The integration must exist and the caller must be allowed to read it.\n- Only the last 20 raw events of an integration are kept, for 7 days; the list is for checking rules, not for searching history.\n- A stored sample keeps its description up to 8 KiB (`description_truncated` marks one that was cut); an event larger than 64 KiB is not kept at all.\n- `dropped` marks a sample the integration discarded before it became an alert.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-sample-read-list", + "metadata": { + "sidebarTitle": "List recent event samples" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentSampleListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "received_at": 1792657352, + "event": { + "title": "CPU usage 94% on checkout-7", + "title_rule": "$service::$check", + "description": "CPU usage above 90% for 5 minutes.", + "alert_key": "cpu-usage-high:checkout-7", + "event_status": "Critical", + "event_severity": "Critical", + "event_time": 1792657345, + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + }, + "images": [] + }, + "description_truncated": false + } + ] + } + } + } + } + }, + "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/EnrichmentSampleListRequest" + }, + "example": { + "integration_id": 6113996590131 + } + } + } + } + } } }, "security": [ diff --git a/api-reference/openapi.zh.json b/api-reference/openapi.zh.json index 5d1f7526..b8567d25 100644 --- a/api-reference/openapi.zh.json +++ b/api-reference/openapi.zh.json @@ -23651,6 +23651,14 @@ "type": "string", "description": "该条目的显示别名;发送时不使用。" }, + "disable_at": { + "type": "boolean", + "description": "是否关闭该机器人的 @ 提醒:`true` 关闭,`false` 强制开启。不传则沿用原有行为——企业微信默认开启,其他机器人类型仅在设置了 `user_schema_id` 时开启。" + }, + "user_schema_id": { + "type": "string", + "description": "机器人解析 @ 提醒所用的用户映射规则 ID(24 位 ObjectID 十六进制串)。飞书机器人开启 @ 提醒时必须提供;保存时会转为小写。" + }, "data_source_id": { "type": "integer", "format": "int64", @@ -34000,6 +34008,11 @@ "format": "int64", "description": "最近收到事件时间的 Unix 时间戳(秒),尚未收到事件时为 `0`。" }, + "last_source_time": { + "type": "integer", + "format": "int64", + "description": "最近一次从上游工具收到事件的时间戳(Unix 秒),包含随后被丢弃、未成为告警的事件;尚未收到过事件时为 `0`。" + }, "editable": { "type": "boolean", "description": "当前调用者是否通过集成对象权限校验;执行写操作还需集成中心管理权限。" @@ -34185,6 +34198,11 @@ "format": "int64", "description": "最近收到事件时间的 Unix 时间戳(秒),尚未收到事件时为 `0`。" }, + "last_source_time": { + "type": "integer", + "format": "int64", + "description": "最近一次从上游工具收到事件的时间戳(Unix 秒),包含随后被丢弃、未成为告警的事件;尚未收到过事件时为 `0`。" + }, "editable": { "type": "boolean", "description": "当前调用者是否通过集成对象权限校验;执行写操作还需集成中心管理权限。" @@ -36229,6 +36247,687 @@ "$ref": "#/components/schemas/RumDashboardTextViz" } ] + }, + "AlertEvent": { + "type": "object", + "description": "一条原始告警事件,与接入管道接收和存储的结构一致。", + "required": [ + "event_status" + ], + "properties": { + "title": { + "type": "string", + "description": "事件标题。未提供 `title_rule` 时必填;两者共同决定告警标题的来源。" + }, + "title_rule": { + "type": "string", + "description": "标题模板,例如 `$service::$alertname`;`title` 为空时用它从 `labels` 生成标题。" + }, + "description": { + "type": "string", + "description": "事件描述,超过 2048 字符会被截断。" + }, + "alert_key": { + "type": "string", + "description": "用于将多个事件合并到同一告警的去重键。可为空:预览会随机生成一个键,因此不会发生合并。" + }, + "event_status": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "事件状态。`Critical`、`Warning`、`Info` 为触发事件,`Ok` 为恢复事件。" + }, + "event_severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ], + "description": "触发事件携带的严重级别。预览会在触发事件上用 `event_status` 覆盖它。" + }, + "event_time": { + "type": "integer", + "format": "int64", + "description": "Unix 时间戳(秒)。预览使用当前时间,传入值会被忽略。" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "事件标签集合,最多 50 项;键为标签名,值为字符串。" + }, + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertImage" + }, + "description": "事件附带的图片。" + } + } + }, + "EnrichmentPreviewEvent": { + "type": "object", + "description": "标签增强预览当时的事件。", + "required": [ + "title", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "执行到当前步骤时的事件标题。" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "执行到当前步骤时的标签集合。" + } + } + }, + "EnrichmentSample": { + "type": "object", + "description": "集成收到的一条原始事件,即进入标签增强之前的样子。", + "required": [ + "received_at", + "event", + "description_truncated" + ], + "properties": { + "received_at": { + "type": "integer", + "format": "int64", + "description": "集成收到该事件的时间戳(Unix 秒)。" + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "原始事件,尚未经过任何标签增强规则。" + }, + "description_truncated": { + "type": "boolean", + "description": "存储的描述被截到样本大小上限时为 `true`。" + }, + "dropped": { + "type": "boolean", + "description": "集成在事件成为告警之前将其丢弃时为 `true`;为 `false` 时不返回该字段。" + } + } + }, + "EnrichStep": { + "type": "object", + "description": "单条标签增强规则对事件做了什么。", + "required": [ + "index", + "kind", + "matched", + "skipped_reason", + "detail", + "added", + "removed", + "changed", + "mapping_row" + ], + "properties": { + "index": { + "type": "integer", + "description": "规则在 `rules` 中的位置,从 0 开始。" + }, + "kind": { + "type": "string", + "enum": [ + "extraction", + "composition", + "mapping", + "drop" + ], + "description": "执行过的规则类型。\n| 取值 | 含义 |\n|---|---|\n| `extraction` | 通过正则或 GJson 从事件 `title`、`description` 或 `labels.*` 中提取值并写入标签。 |\n| `composition` | 用模板渲染事件并把结果写入标签。 |\n| `mapping` | 从映射规则或外部映射 API 查询标签。 |\n| `drop` | 从告警中删除指定标签。 |" + }, + "matched": { + "type": "boolean", + "description": "规则的 `if` 条件是否全部满足;`false` 表示规则没有改变任何标签。" + }, + "skipped_reason": { + "type": "string", + "description": "规则被跳过的原因:`condition_not_met`、`regex_not_matched`、`source_label_missing`、`mapping_row_not_found`、`result_label_exists` 或 `error`。规则正常执行时为空。" + }, + "detail": { + "type": "string", + "description": "规则自身的细节:命中的映射行、渲染出的值,`skipped_reason` 为 `error` 时为错误信息。" + }, + "added": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "规则新写入的标签;未新增时为 `null`。" + }, + "removed": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "规则删除的标签;未删除时为 `null`。" + }, + "changed": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "规则改写的标签,每个值为 `[旧值, 新值]` 两元数组;未改写时为 `null`。" + }, + "mapping_row": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "规则命中的映射行;不是映射规则或未命中时为 `null`。" + } + } + }, + "AlertPipelinePreviewEvent": { + "type": "object", + "description": "告警处理预览当时的事件。", + "required": [ + "title", + "description", + "severity", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "事件标题。" + }, + "description": { + "type": "string", + "description": "事件描述。" + }, + "severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "此时事件携带的严重级别。" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "标签集合。" + } + } + }, + "PipelineStep": { + "type": "object", + "description": "单条告警处理规则对事件做了什么。", + "required": [ + "index", + "kind", + "result", + "detail" + ], + "properties": { + "index": { + "type": "integer", + "description": "规则在 `rules` 中的位置,从 0 开始。" + }, + "kind": { + "type": "string", + "enum": [ + "title_reset", + "description_reset", + "severity_reset", + "alert_drop", + "alert_inhibit" + ], + "description": "执行过的规则类型。\n| 取值 | 含义 |\n|---|---|\n| `title_reset` | 用规则模板改写标题。 |\n| `description_reset` | 用规则模板改写描述。 |\n| `severity_reset` | 把严重级别和状态重置为规则中的 `severity`。 |\n| `alert_drop` | 直接丢弃事件,不产生告警。 |\n| `alert_inhibit` | 存在匹配的活跃源告警时丢弃事件。 |" + }, + "result": { + "type": "string", + "enum": [ + "applied", + "not_matched", + "not_executed" + ], + "description": "规则结果:`applied`(改变了事件或终止了后续处理)、`not_matched`(`if` 条件没有全部满足)、`not_executed`(前面的规则已终止处理,或事件是恢复事件)。" + }, + "detail": { + "type": "string", + "description": "上述结果对应的 `condition_not_met`、`no_active_source_alert`、`inhibit_not_evaluated` 或 `recovery_event`;其他情况为结果值或错误信息。" + } + } + }, + "AlertEmailPreviewSettings": { + "type": "object", + "description": "要预览的邮件集成配置,与保存接口接受的形状一致。", + "properties": { + "mode": { + "type": "string", + "enum": [ + "alwaysTrigger", + "triggerByTitle", + "triggerOrCloseByRule" + ], + "description": "集成判定一封邮件归属的方式;省略时默认 `alwaysTrigger`。\n- `alwaysTrigger`:每封邮件都是独立告警,键随机生成。\n- `triggerByTitle`:每封邮件都是触发事件,告警键由邮件主题哈希得到。\n- `triggerOrCloseByRule`:由 `rules` 决定邮件是触发、关闭还是丢弃,未命中的由 `default` 处理。" + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertEmailRule" + }, + "description": "`mode` 为 `triggerOrCloseByRule` 时按顺序匹配的规则,每条都必须是非空对象,最多 50 条。" + }, + "default": { + "type": "string", + "enum": [ + "trigger", + "discard" + ], + "description": "`mode` 为 `triggerOrCloseByRule` 且没有规则命中时的处理方式:`trigger` 转为触发事件,`discard` 丢弃。" + } + } + }, + "AlertEmailRule": { + "type": "object", + "description": "匹配一封邮件并从中提取告警键的规则。", + "required": [ + "type", + "extract_from", + "extract_pattern", + "filters" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "trigger", + "close" + ], + "description": "`trigger` 表示命中的邮件转为触发事件,`close` 转为恢复事件。" + }, + "extract_from": { + "type": "string", + "enum": [ + "title", + "description" + ], + "description": "告警键从邮件的哪一部分提取:`title` 或 `description`。取 `description` 时依次搜索正文纯文本、带表格的正文、描述。" + }, + "extract_pattern": { + "type": "string", + "description": "提取告警键的正则表达式,捕获到的分组用 `,` 拼接为键来源;没有捕获到任何内容时回退为邮件主题。" + }, + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterCondition" + }, + "description": "邮件必须全部满足的条件;传 `[]` 表示匹配所有邮件。" + } + } + }, + "AlertEmailPreviewEmail": { + "type": "object", + "description": "要预览的邮件内容。", + "properties": { + "subject": { + "type": "string", + "description": "邮件主题。" + }, + "body": { + "type": "string", + "description": "邮件正文:以 `<` 开头按 HTML 处理,否则按纯文本处理。" + }, + "from": { + "type": "string", + "description": "发件人地址。" + }, + "eml": { + "type": "string", + "description": "整封邮件文件(`.eml`)的 base64 内容。提供后它会替代 `subject`、`body` 和 `from`,并按 SMTP 服务端的解析方式解析。" + } + } + }, + "AlertEmailPreviewEvent": { + "type": "object", + "description": "这封邮件会产生的告警事件。", + "required": [ + "title", + "description", + "event_status", + "event_severity", + "labels" + ], + "properties": { + "title": { + "type": "string", + "description": "事件标题。" + }, + "description": { + "type": "string", + "description": "事件描述。" + }, + "event_status": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "这封邮件产生的事件状态。" + }, + "event_severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ], + "description": "触发事件的严重级别;恢复事件为空。" + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "从邮件中提取的标签:正文、发件人、收件人和主题都会以标签形式暴露。" + } + } + }, + "AlertEmailPreviewParsed": { + "type": "object", + "description": "转换时实际读到的邮件内容。", + "required": [ + "subject", + "from", + "body", + "body_text" + ], + "properties": { + "subject": { + "type": "string", + "description": "解析后的邮件主题。" + }, + "from": { + "type": "string", + "description": "从邮件中取到的发件人地址。" + }, + "body": { + "type": "string", + "description": "转换使用的正文:存在 HTML 部分时用它,否则用纯文本部分。" + }, + "body_text": { + "type": "string", + "description": "纯文本正文;从描述中提取告警键时优先在这里搜索。" + } + } + }, + "EnrichmentPreviewRequest": { + "type": "object", + "description": "`POST /enrichment/preview` 的请求体。", + "required": [ + "integration_id", + "event" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "预览所依据的集成 ID;发送的规则不会被保存。" + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/EnrichRule" + }, + "description": "按顺序尝试的标签增强规则,最多 50 条;不会使用该集成已存的规则。" + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "要跑规则的事件。" + } + } + }, + "EnrichmentPreviewResponse": { + "type": "object", + "description": "标签增强预览的结果。", + "required": [ + "before", + "after", + "steps" + ], + "properties": { + "before": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "事件进入时的样子。" + }, + "after": { + "$ref": "#/components/schemas/EnrichmentPreviewEvent", + "description": "规则执行后的事件,触发事件已按接入方式渲染 `[TPL]` 标签、标题和描述。" + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichStep" + }, + "description": "每条规则一项,按执行顺序排列。" + } + } + }, + "EnrichmentSampleListRequest": { + "type": "object", + "description": "`POST /enrichment/sample/list` 的请求体。", + "required": [ + "integration_id" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "要查看最近原始事件的集成 ID。" + } + } + }, + "EnrichmentSampleListResponse": { + "type": "object", + "description": "某个集成最近的原始事件。", + "required": [ + "items" + ], + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnrichmentSample" + }, + "description": "样本列表,最新的在前;尚未收到事件时为空。" + } + } + }, + "AlertPipelinePreviewRequest": { + "type": "object", + "description": "`POST /alert/pipeline/preview` 的请求体。", + "required": [ + "integration_id", + "event" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "预览所用的集成 ID;该集成已存的标签增强会先执行。" + }, + "rules": { + "type": "array", + "maxItems": 50, + "items": { + "$ref": "#/components/schemas/AlertPipeline" + }, + "description": "按顺序尝试的告警处理规则,最多 50 条;不会使用该集成已存的处理规则。" + }, + "event": { + "$ref": "#/components/schemas/AlertEvent", + "description": "要跑规则的事件。" + } + } + }, + "AlertPipelinePreviewResponse": { + "type": "object", + "description": "告警处理预览的结果。", + "required": [ + "is_recovery", + "before", + "after", + "dropped", + "inhibited", + "steps" + ], + "properties": { + "is_recovery": { + "type": "boolean", + "description": "事件是恢复事件时为 `true`:接入会直接关闭告警,不执行处理规则。" + }, + "before": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "事件进入时的样子。" + }, + "after": { + "$ref": "#/components/schemas/AlertPipelinePreviewEvent", + "description": "规则执行后、通知模板渲染出的事件。" + }, + "dropped": { + "type": "boolean", + "description": "某条规则丢弃了该事件、不会产生告警时为 `true`。" + }, + "inhibited": { + "type": "boolean", + "description": "某条规则因存在匹配的活跃源告警而抑制了该事件时为 `true`。" + }, + "steps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PipelineStep" + }, + "description": "每条规则一项,按执行顺序排列。" + } + } + }, + "AlertEmailPreviewRequest": { + "type": "object", + "description": "`POST /alert/email/preview` 的请求体。", + "required": [ + "settings", + "email" + ], + "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "提供初始配置的邮件集成 ID。传 `0` 或不传等价于控制台在新建页面、集成尚不存在时的场景。" + }, + "settings": { + "$ref": "#/components/schemas/AlertEmailPreviewSettings", + "description": "要预览的配置,按保存接口的规则校验。" + }, + "email": { + "$ref": "#/components/schemas/AlertEmailPreviewEmail", + "description": "要转换的邮件。" + } + } + }, + "AlertEmailPreviewResponse": { + "type": "object", + "description": "配置对这封邮件的判定,以及转换实际读到的内容。", + "required": [ + "result", + "matched_rule", + "key_source", + "key_fallback", + "alert_key", + "event", + "email" + ], + "properties": { + "result": { + "type": "string", + "enum": [ + "trigger", + "close", + "discard" + ], + "description": "配置对这封邮件的判定:`trigger`(触发事件)、`close`(恢复事件)、`discard`(丢弃)。" + }, + "matched_rule": { + "type": [ + "integer", + "null" + ], + "description": "命中的规则下标,从 0 开始;没有规则命中时为 `null`,`alwaysTrigger` 与 `triggerByTitle` 模式下始终为 `null`。" + }, + "key_source": { + "type": "string", + "description": "告警键的哈希来源。`alwaysTrigger` 模式下每封邮件各自成为告警,或被丢弃时为空。" + }, + "key_fallback": { + "type": "boolean", + "description": "规则的正则没有捕获到内容、改用邮件主题作为键来源时为 `true`。" + }, + "alert_key": { + "type": "string", + "description": "`key_source` 的哈希值。`alwaysTrigger` 模式下每封邮件使用随机键,此字段为空。" + }, + "event": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewEvent" + }, + { + "type": "null" + } + ], + "description": "这封邮件产生的事件;邮件被丢弃时为 `null`。" + }, + "email": { + "oneOf": [ + { + "$ref": "#/components/schemas/AlertEmailPreviewParsed" + }, + { + "type": "null" + } + ], + "description": "转换实际读到的邮件内容;无法解析邮件时为 `null`。" + } + } } }, "securitySchemes": { @@ -74873,6 +75572,522 @@ } } } + }, + "/alert/email/preview": { + "post": { + "operationId": "alert-read-email-preview", + "summary": "预览邮件转告警效果", + "description": "用未保存的邮件集成配置,按接入的方式处理一封邮件,返回判定结果与生成的事件。", + "tags": [ + "On-call/集成中心" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 不会写入任何数据:不创建也不修改集成、告警或事件。\n- `integration_id` 只用于带入该集成已存的地址前缀;地址本身不参与处理,因此在新建页面同样可用。\n- `settings` 会走保存接口同一套校验:不支持的 `mode`、规则 `type`、`extract_from` 或非法的 `extract_pattern` 会在解析邮件之前就返回 `InvalidParameter`。\n- 提供 `eml` 时按邮件文件解析,并受 SMTP 邮件大小上限约束;响应中的 `email` 展示解析器实际读到的内容。\n- 配置丢弃该邮件时 `event` 为 `null`;邮件无法解析时 `email` 为 `null`。\n- `alwaysTrigger` 模式下每封邮件都是独立告警,`alert_key` 与 `key_source` 返回空。", + "href": "/zh/api-reference/on-call/integrations/alert-read-email-preview", + "metadata": { + "sidebarTitle": "预览邮件转告警效果" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertEmailPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "result": "trigger", + "matched_rule": 0, + "key_source": "checkout 5xx rate above 2%", + "key_fallback": false, + "alert_key": "8f14e45fceea167a5a36dedd4bea2543", + "event": { + "title": "[ALERT] checkout 5xx rate above 2%", + "description": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "event_status": "Critical", + "event_severity": "Critical", + "labels": { + "from": "alerts@acme.example.com", + "subject": "[ALERT] checkout 5xx rate above 2%" + } + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "from": "alerts@acme.example.com", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "body_text": "The checkout service 5xx rate is 3.4% over the last 5 minutes." + } + } + } + } + } + }, + "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/AlertEmailPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "settings": { + "mode": "triggerOrCloseByRule", + "rules": [ + { + "type": "trigger", + "extract_from": "title", + "extract_pattern": "^\\[ALERT\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[ALERT]/" + ] + } + ] + }, + { + "type": "close", + "extract_from": "title", + "extract_pattern": "^\\[OK\\]\\s*(?P.*)$", + "filters": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/[OK]/" + ] + } + ] + } + ], + "default": "discard" + }, + "email": { + "subject": "[ALERT] checkout 5xx rate above 2%", + "body": "The checkout service 5xx rate is 3.4% over the last 5 minutes.", + "from": "alerts@acme.example.com" + } + } + } + } + } + } + }, + "/alert/pipeline/preview": { + "post": { + "operationId": "alert-read-pipeline-preview", + "summary": "预览告警处理规则效果", + "description": "用未保存的告警处理规则按接入的方式处理一个事件,返回处理前后的差异。", + "tags": [ + "On-call/告警管理" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 不会保存任何内容,也不创建告警或事件。\n- 该集成已存的标签增强规则会先执行,然后按顺序执行你传入的 `rules`,作用在增强后的事件上。\n- 恢复(`Ok`)事件会直接关闭告警、不执行处理规则:`is_recovery` 为 `true`,每一步都是 `not_executed`,`detail` 为 `recovery_event`。\n- `dropped`、`inhibited` 说明是哪类规则中断了事件:`alert_drop` 直接丢弃,`alert_inhibit` 在存在匹配的活跃源告警时丢弃。该规则之后的步骤为 `not_executed`。\n- 没有规则命中时,`after` 是通知模板渲染后的事件,即在协作空间中会看到的内容。", + "href": "/zh/api-reference/on-call/alerts/alert-read-pipeline-preview", + "metadata": { + "sidebarTitle": "预览告警处理规则效果" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelinePreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "is_recovery": false, + "before": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "after": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "severity": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + }, + "dropped": false, + "inhibited": false, + "steps": [ + { + "index": 0, + "kind": "severity_reset", + "result": "not_matched", + "detail": "condition_not_met" + }, + { + "index": 1, + "kind": "alert_drop", + "result": "not_matched", + "detail": "condition_not_met" + } + ] + } + } + } + } + }, + "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/AlertPipelinePreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "severity_reset", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "test" + ] + } + ], + "settings": { + "severity": "Info" + } + }, + { + "kind": "alert_drop", + "if": [ + { + "key": "title", + "oper": "IN", + "vals": [ + "/.*noise.*/" + ] + } + ], + "settings": {} + } + ], + "event": { + "title": "Disk usage 95% on db-3", + "description": "Root filesystem is 95% full on db-3.", + "event_status": "Warning", + "labels": { + "service": "mysql", + "env": "prod", + "host": "db-3" + } + } + } + } + } + } + } + }, + "/enrichment/preview": { + "post": { + "operationId": "enrichment-read-preview", + "summary": "预览标签增强规则效果", + "description": "用未保存的标签增强规则按接入的方式处理一个事件,返回规则逐步的结果。", + "tags": [ + "On-call/标签增强" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 不会保存任何内容,也不创建告警或事件。\n- `integration_id` 必须是本账户的集成,且调用方有权读取它。\n- `mapping_type` 为 `api` 的 `mapping` 规则会用已存的请求头调用账户的映射 API,因此还需要编辑该集成的权限,否则请求失败。\n- `before` 是事件进入时的样子,`after` 是规则执行后的事件;`steps` 逐条说明规则是否满足条件、为什么被跳过、新增/删除/改写了哪些标签。\n- 触发事件会按接入在增强后的方式渲染,因此 `after` 中的 `[TPL]` 标签、标题和描述就是最终形态。\n- `if` 的条件键必须来自告警或变更事件的键(`title`、`description`、`labels.` 等),其他键返回 `InvalidParameter`。", + "href": "/zh/api-reference/on-call/alert-enrichment/enrichment-read-preview", + "metadata": { + "sidebarTitle": "预览标签增强规则效果" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentPreviewResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "before": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + } + }, + "after": { + "title": "CPU usage 94% on checkout-7", + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7", + "service_name": "checkout" + } + }, + "steps": [ + { + "index": 0, + "kind": "extraction", + "matched": true, + "skipped_reason": "", + "detail": "checkout", + "added": { + "service_name": "checkout" + }, + "removed": null, + "changed": null, + "mapping_row": null + } + ] + } + } + } + } + }, + "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/EnrichmentPreviewRequest" + }, + "example": { + "integration_id": 6113996590131, + "rules": [ + { + "kind": "extraction", + "if": [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "prod" + ] + } + ], + "settings": { + "source_field": "labels.host", + "result_label": "service_name", + "pattern": "^(?P[a-z0-9-]+)-\\d+$", + "override": false + } + } + ], + "event": { + "title": "CPU usage 94% on checkout-7", + "description": "CPU usage above 90% for 5 minutes.", + "event_status": "Critical", + "labels": { + "env": "prod", + "host": "checkout-7", + "check": "cpu" + } + } + } + } + } + } + } + }, + "/enrichment/sample/list": { + "post": { + "operationId": "enrichment-sample-read-list", + "summary": "查询事件样本列表", + "description": "查询某个集成最近收到的原始事件,最新的在前。", + "tags": [ + "On-call/标签增强" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **协作空间管理**(`on-call`)或 **集成中心查看**(`on-call`)或 **集成中心管理**(`on-call`) |\n\n## 使用说明\n\n- 样本是进入标签增强时的事件,因此能看到规则实际匹配的标签。\n- 集成必须存在,且调用方有权读取它。\n- 每个集成只保留最近 20 条原始事件,保存 7 天;该列表用于核对规则,不用于检索历史。\n- 样本保存最多 8 KiB 的描述(被截断时 `description_truncated` 为 `true`);超过 64 KiB 的事件不会保留。\n- `dropped` 标记集成在事件成为告警之前丢弃的样本。", + "href": "/zh/api-reference/on-call/alert-enrichment/enrichment-sample-read-list", + "metadata": { + "sidebarTitle": "查询事件样本列表" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/EnrichmentSampleListResponse" + } + } + } + ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "received_at": 1792657352, + "event": { + "title": "CPU usage 94% on checkout-7", + "title_rule": "$service::$check", + "description": "CPU usage above 90% for 5 minutes.", + "alert_key": "cpu-usage-high:checkout-7", + "event_status": "Critical", + "event_severity": "Critical", + "event_time": 1792657345, + "labels": { + "check": "cpu", + "env": "prod", + "host": "checkout-7" + }, + "images": [] + }, + "description_truncated": false + } + ] + } + } + } + } + }, + "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/EnrichmentSampleListRequest" + }, + "example": { + "integration_id": 6113996590131 + } + } + } + } + } } }, "security": [ diff --git a/docs.json b/docs.json index 9a8375d4..305a6ffd 100644 --- a/docs.json +++ b/docs.json @@ -4133,6 +4133,7 @@ "POST /alert/pipeline/info", "POST /alert/pipeline/list", "POST /alert/pipeline/upsert", + "POST /alert/pipeline/preview", "POST /alert-event/list" ] }, @@ -4151,7 +4152,8 @@ "POST /integration/delete", "POST /integration/enable", "POST /integration/disable", - "POST /integration/key/rotate" + "POST /integration/key/rotate", + "POST /alert/email/preview" ] }, { @@ -4231,6 +4233,8 @@ "POST /enrichment/info", "POST /enrichment/list", "POST /enrichment/upsert", + "POST /enrichment/preview", + "POST /enrichment/sample/list", { "group": "映射 Schema", "icon": "table-columns", @@ -5906,6 +5910,7 @@ "POST /alert/pipeline/info", "POST /alert/pipeline/list", "POST /alert/pipeline/upsert", + "POST /alert/pipeline/preview", "POST /alert-event/list" ] }, @@ -5924,7 +5929,8 @@ "POST /integration/delete", "POST /integration/enable", "POST /integration/disable", - "POST /integration/key/rotate" + "POST /integration/key/rotate", + "POST /alert/email/preview" ] }, { @@ -6004,6 +6010,8 @@ "POST /enrichment/info", "POST /enrichment/list", "POST /enrichment/upsert", + "POST /enrichment/preview", + "POST /enrichment/sample/list", { "group": "Mapping schemas", "icon": "table-columns", diff --git a/en/openapi/api-catalog.mdx b/en/openapi/api-catalog.mdx index 1ab32d55..87ff14de 100644 --- a/en/openapi/api-catalog.mdx +++ b/en/openapi/api-catalog.mdx @@ -3,13 +3,13 @@ title: "API catalog" description: "Complete list of Flashduty Open API endpoints, organized by product module with links to detailed documentation" --- -Flashduty Open API provides **379** endpoints covering five major modules: On-call, Monitors, RUM, AI SRE, and Platform. All endpoints use unified authentication and request specifications. See [Quick Start](/en/openapi/introduction) for details. +Flashduty Open API provides **383** endpoints covering five major modules: On-call, Monitors, RUM, AI SRE, and Platform. All endpoints use unified authentication and request specifications. See [Quick Start](/en/openapi/introduction) for details. All endpoint URLs use `https://api.flashcat.cloud` as the base, authenticated through APP Key through query string. - + ### Incidents @@ -125,6 +125,7 @@ All endpoint URLs use `https://api.flashcat.cloud` as the base, authenticated th | POST | [`/alert/pipeline/info`](/en/api-reference/on-call/alerts/alert-read-pipeline-info) | Get alert pipeline | | POST | [`/alert/pipeline/list`](/en/api-reference/on-call/alerts/alert-read-pipeline-list) | List alert pipelines | | POST | [`/alert/pipeline/upsert`](/en/api-reference/on-call/alerts/alert-write-pipeline-upsert) | Create or update alert pipeline | +| POST | [`/alert/pipeline/preview`](/en/api-reference/on-call/alerts/alert-read-pipeline-preview) | Preview alert pipeline processing | | POST | [`/alert-event/list`](/en/api-reference/on-call/alerts/alert-event-read-list) | List raw alert events | ### Integrations @@ -145,6 +146,7 @@ The `/integration/*` management APIs cover public (account-level) integrations, | POST | [`/integration/enable`](/en/api-reference/on-call/integrations/integration-api-write-enable) | Enable integration | | POST | [`/integration/disable`](/en/api-reference/on-call/integrations/integration-api-write-disable) | Disable integration | | POST | [`/integration/key/rotate`](/en/api-reference/on-call/integrations/integration-api-write-rotate-key) | Rotate integration key | +| POST | [`/alert/email/preview`](/en/api-reference/on-call/integrations/alert-read-email-preview) | Preview email-to-alert conversion | ### Schedules @@ -197,6 +199,8 @@ The `/integration/*` management APIs cover public (account-level) integrations, | POST | [`/enrichment/info`](/en/api-reference/on-call/alert-enrichment/enrichment-read-info) | Get enrichment rules | | POST | [`/enrichment/list`](/en/api-reference/on-call/alert-enrichment/enrichment-read-list) | List enrichment rules | | POST | [`/enrichment/upsert`](/en/api-reference/on-call/alert-enrichment/enrichment-write-upsert) | Upsert enrichment rules | +| POST | [`/enrichment/preview`](/en/api-reference/on-call/alert-enrichment/enrichment-read-preview) | Preview enrichment rule results | +| POST | [`/enrichment/sample/list`](/en/api-reference/on-call/alert-enrichment/enrichment-sample-read-list) | List recent event samples | | POST | [`/enrichment/mapping/schema/list`](/en/api-reference/on-call/alert-enrichment/mapping-schema-read-list) | List mapping schemas | | POST | [`/enrichment/mapping/schema/info`](/en/api-reference/on-call/alert-enrichment/mapping-schema-read-info) | Get mapping schema detail | | POST | [`/enrichment/mapping/schema/create`](/en/api-reference/on-call/alert-enrichment/mapping-schema-write-create) | Create mapping schema | diff --git a/zh/openapi/api-catalog.mdx b/zh/openapi/api-catalog.mdx index ffa81722..923aebf8 100644 --- a/zh/openapi/api-catalog.mdx +++ b/zh/openapi/api-catalog.mdx @@ -3,13 +3,13 @@ title: "API 目录" description: "Flashduty Open API 接口完整列表,按产品模块组织并链接到详细文档" --- -Flashduty Open API 提供 **379** 个接口,覆盖 On-call、Monitors、RUM、AI SRE 和平台五个主要模块。所有接口使用统一认证方式和请求规范。详情参见[快速开始](/zh/openapi/introduction)。 +Flashduty Open API 提供 **383** 个接口,覆盖 On-call、Monitors、RUM、AI SRE 和平台五个主要模块。所有接口使用统一认证方式和请求规范。详情参见[快速开始](/zh/openapi/introduction)。 所有接口 URL 均以 `https://api.flashcat.cloud` 为 base,通过 query string 中的 APP Key 认证。 - + ### 故障管理 @@ -125,6 +125,7 @@ Flashduty Open API 提供 **379** 个接口,覆盖 On-call、Monitors、RUM、 | POST | [`/alert/pipeline/info`](/zh/api-reference/on-call/alerts/alert-read-pipeline-info) | 查看告警处理规则 | | POST | [`/alert/pipeline/list`](/zh/api-reference/on-call/alerts/alert-read-pipeline-list) | 批量查询告警处理规则 | | POST | [`/alert/pipeline/upsert`](/zh/api-reference/on-call/alerts/alert-write-pipeline-upsert) | 创建或更新告警处理规则 | +| POST | [`/alert/pipeline/preview`](/zh/api-reference/on-call/alerts/alert-read-pipeline-preview) | 预览告警处理规则效果 | | POST | [`/alert-event/list`](/zh/api-reference/on-call/alerts/alert-event-read-list) | 查询原始告警事件列表 | ### 集成中心 @@ -145,6 +146,7 @@ Flashduty Open API 提供 **379** 个接口,覆盖 On-call、Monitors、RUM、 | POST | [`/integration/enable`](/zh/api-reference/on-call/integrations/integration-api-write-enable) | 启用集成 | | POST | [`/integration/disable`](/zh/api-reference/on-call/integrations/integration-api-write-disable) | 禁用集成 | | POST | [`/integration/key/rotate`](/zh/api-reference/on-call/integrations/integration-api-write-rotate-key) | 轮换集成 Key | +| POST | [`/alert/email/preview`](/zh/api-reference/on-call/integrations/alert-read-email-preview) | 预览邮件转告警效果 | ### 值班排班 @@ -197,6 +199,8 @@ Flashduty Open API 提供 **379** 个接口,覆盖 On-call、Monitors、RUM、 | POST | [`/enrichment/info`](/zh/api-reference/on-call/alert-enrichment/enrichment-read-info) | 查看富化规则 | | POST | [`/enrichment/list`](/zh/api-reference/on-call/alert-enrichment/enrichment-read-list) | 批量查询富化规则 | | POST | [`/enrichment/upsert`](/zh/api-reference/on-call/alert-enrichment/enrichment-write-upsert) | 创建或替换富化规则 | +| POST | [`/enrichment/preview`](/zh/api-reference/on-call/alert-enrichment/enrichment-read-preview) | 预览标签增强规则效果 | +| POST | [`/enrichment/sample/list`](/zh/api-reference/on-call/alert-enrichment/enrichment-sample-read-list) | 查询事件样本列表 | | POST | [`/enrichment/mapping/schema/list`](/zh/api-reference/on-call/alert-enrichment/mapping-schema-read-list) | 查询映射规则列表 | | POST | [`/enrichment/mapping/schema/info`](/zh/api-reference/on-call/alert-enrichment/mapping-schema-read-info) | 查看映射规则详情 | | POST | [`/enrichment/mapping/schema/create`](/zh/api-reference/on-call/alert-enrichment/mapping-schema-write-create) | 创建映射规则 | From 91d3b2510ce4a97dbf04dc8e6482cd24cbd6efdd Mon Sep 17 00:00:00 2001 From: flashduty-bot Date: Thu, 22 Oct 2026 08:38:43 +0000 Subject: [PATCH 2/3] docs(api-reference): refresh API path redirects for the 4 new preview endpoints (api-review 2026-10-22) --- docs.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs.json b/docs.json index 305a6ffd..ae5eab6f 100644 --- a/docs.json +++ b/docs.json @@ -1503,6 +1503,10 @@ "source": "/alert-event/list", "destination": "/zh/api-reference/on-call/alerts/alert-event-read-list" }, + { + "source": "/alert/email/preview", + "destination": "/zh/api-reference/on-call/integrations/alert-read-email-preview" + }, { "source": "/alert/event/list", "destination": "/zh/api-reference/on-call/alerts/alert-read-event-list" @@ -1535,6 +1539,10 @@ "source": "/alert/pipeline/list", "destination": "/zh/api-reference/on-call/alerts/alert-read-pipeline-list" }, + { + "source": "/alert/pipeline/preview", + "destination": "/zh/api-reference/on-call/alerts/alert-read-pipeline-preview" + }, { "source": "/alert/pipeline/upsert", "destination": "/zh/api-reference/on-call/alerts/alert-write-pipeline-upsert" @@ -1795,6 +1803,14 @@ "source": "/enrichment/mapping/schema/update", "destination": "/zh/api-reference/on-call/alert-enrichment/mapping-schema-write-update" }, + { + "source": "/enrichment/preview", + "destination": "/zh/api-reference/on-call/alert-enrichment/enrichment-read-preview" + }, + { + "source": "/enrichment/sample/list", + "destination": "/zh/api-reference/on-call/alert-enrichment/enrichment-sample-read-list" + }, { "source": "/enrichment/upsert", "destination": "/zh/api-reference/on-call/alert-enrichment/enrichment-write-upsert" From d23d419831af9d706fd014ab1f31ea10ab95d269 Mon Sep 17 00:00:00 2001 From: flashduty-bot Date: Thu, 22 Oct 2026 08:40:11 +0000 Subject: [PATCH 3/3] docs(api-reference): canonical redirect ordering after merging main (api-review 2026-10-22) origin/main at 9b6eeba3 already failed scripts/api_path_redirects.py --check: the two RUM error-reporting redirects added by the doc-review merges sit at the end of the managed list instead of their sorted position. Running the repo's own script reorders them (8 insertions / 8 deletions, no semantic change) so the lint job can pass on this branch. --- docs.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs.json b/docs.json index 9c20b8b6..288900ae 100644 --- a/docs.json +++ b/docs.json @@ -1495,6 +1495,14 @@ "source": "/en/rum/error-tracking/erro-reporting/:slug*", "destination": "/en/rum/error-tracking/error-reporting/:slug*" }, + { + "source": "/zh/rum/error-tracking/erro-reporting/web", + "destination": "/zh/rum/error-tracking/error-reporting/web" + }, + { + "source": "/en/rum/error-tracking/erro-reporting/web", + "destination": "/en/rum/error-tracking/error-reporting/web" + }, { "source": "/account/info", "destination": "/zh/api-reference/platform/account/account-read-info" @@ -3026,14 +3034,6 @@ { "source": "/webhook/history/list", "destination": "/zh/api-reference/on-call/integrations/webhook-history-list" - }, - { - "source": "/zh/rum/error-tracking/erro-reporting/web", - "destination": "/zh/rum/error-tracking/error-reporting/web" - }, - { - "source": "/en/rum/error-tracking/erro-reporting/web", - "destination": "/en/rum/error-tracking/error-reporting/web" } ], "navigation": {